<?php

namespace Modules\DentalClinic\Entities;

use Illuminate\Database\Eloquent\Model;
use Modules\ClinicCore\Entities\ClcPatient;

/**
 * One tooth's recorded condition on a shared ClinicCore patient's dental
 * chart (1:many, keyed by clc_patient_id + tooth_number).
 *
 * Storage of tooth_number always stays UNIVERSAL numbering (ADA 1-32). The
 * optional notation_system column only records the dentist's preferred display
 * notation; conversion to FDI/Palmer is a pure display helper (toNotation()).
 */
class DentalToothFinding extends Model
{
    protected $table = 'dental_tooth_findings';
    protected $guarded = ['id'];

    protected $casts = [
        'bleeding_on_probing' => 'boolean',
        'probing_depth_mm'    => 'integer',
        'mobility'            => 'integer',
    ];

    /**
     * Condition palette -> [label, badge colour]. Universal numbering.
     *
     * The P5-T2 spec set is: healthy, carious, filled, crowned,
     * bridge_abutment, missing, implant, root_canal. Legacy keys (caries, crown,
     * extraction_needed) are retained so pre-existing chart rows and the
     * existing tooth-chart UI keep rendering unchanged.
     */
    public const CONDITIONS = [
        'healthy'           => ['Healthy',           '#e9ecef'],
        'carious'           => ['Carious',           '#dc3545'],
        'filled'            => ['Filled',            '#0d6efd'],
        'crowned'           => ['Crowned',           '#ffc107'],
        'bridge_abutment'   => ['Bridge abutment',   '#0dcaf0'],
        'root_canal'        => ['Root canal',        '#6f42c1'],
        'implant'           => ['Implant',           '#20c997'],
        'missing'           => ['Missing',           '#343a40'],
        // -- legacy aliases (kept so old data + existing chart keep working) --
        'caries'            => ['Caries',            '#dc3545'],
        'crown'             => ['Crown',             '#ffc107'],
        'extraction_needed' => ['Extraction needed', '#fd7e14'],
    ];

    /** Dark-background conditions (for readable label colour on the chart). */
    public const DARK_CONDITIONS = ['missing', 'root_canal', 'caries', 'carious', 'bridge_abutment', 'implant'];

    /** Endodontic status options. */
    public const ENDO_STATUSES = ['none', 'treated', 'retreated', 'pending'];

    /** Supported display notation systems (storage is always universal 1-32). */
    public const NOTATION_SYSTEMS = ['universal', 'fdi', 'palmer'];

    public function patient()
    {
        return $this->belongsTo(ClcPatient::class, 'clc_patient_id');
    }

    /**
     * Render the stored universal tooth number (1-32) in another notation.
     *
     * FDI (ISO 3950) quadrant.tooth for permanent dentition, and the Palmer
     * quadrant symbol + tooth index. Falls back to the universal number if the
     * value is out of the 1-32 permanent range (e.g. primary/supernumerary).
     *
     * @param  string       $system   universal|fdi|palmer
     * @param  int|null     $universal Defaults to this row's tooth_number.
     * @return string
     */
    public function toNotation(string $system, ?int $universal = null): string
    {
        $u = (int) ($universal ?? $this->tooth_number);
        return static::convertNotation($u, $system);
    }

    /**
     * Static universal -> notation converter so callers (blades, print view,
     * controllers) can convert without a model instance.
     */
    public static function convertNotation(int $universal, string $system): string
    {
        if ($universal < 1 || $universal > 32) {
            return (string) $universal; // out of permanent range — show as-is
        }

        // Universal 1-16 = maxillary (upper) left-molar -> right-molar sweep;
        // 17-32 = mandibular (lower). Map to FDI quadrant/position.
        // FDI permanent quadrants: 1 = upper right, 2 = upper left,
        // 3 = lower left, 4 = lower right. Position 1 (central incisor) .. 8 (3rd molar).
        static $fdi = [
            1 => 18, 2 => 17, 3 => 16, 4 => 15, 5 => 14, 6 => 13, 7 => 12, 8 => 11,
            9 => 21, 10 => 22, 11 => 23, 12 => 24, 13 => 25, 14 => 26, 15 => 27, 16 => 28,
            17 => 38, 18 => 37, 19 => 36, 20 => 35, 21 => 34, 22 => 33, 23 => 32, 24 => 31,
            25 => 41, 26 => 42, 27 => 43, 28 => 44, 29 => 45, 30 => 46, 31 => 47, 32 => 48,
        ];

        $system = strtolower($system);
        if ($system === 'fdi') {
            return (string) $fdi[$universal];
        }

        if ($system === 'palmer') {
            // Palmer: quadrant symbol (⌐ ¬ L Γ) + position 1..8. We approximate
            // the quadrant bracket with a leading marker for plain-text output.
            $code = $fdi[$universal];
            $quadrant = intdiv($code, 10);   // 1..4
            $position = $code % 10;          // 1..8
            $symbols = [1 => '⌐', 2 => '¬', 3 => '_|', 4 => '|_'];
            $sym = $symbols[$quadrant] ?? '';
            // Upper quadrants put the number before/after the bracket; keep it simple.
            return in_array($quadrant, [1, 4], true) ? ($position . $sym) : ($sym . $position);
        }

        return (string) $universal; // universal / unknown
    }
}
