<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Spatie\Permission\Models\Permission;

/**
 * Item 1.4 - Structured Objective exam: templates + per-appointment findings.
 *
 *  vc_exam_templates       - "Standard General Exam", "Orthopedic", "Neuro" etc.
 *  vc_exam_template_items  - the individual rows inside a template (regions
 *                            and findings), each with a response_type
 *                            ('select' / 'grade' / 'measurement' / 'text' /
 *                            'body_map') that drives the UI widget.
 *  vc_appointment_exam_findings - the doctor's filled-in answers per visit,
 *                                 with severity + is_critical flags that
 *                                 feed the Medical Critical Check report
 *                                 (item 4.1).
 *  vc_exam_settings        - per-business defaults (which General template
 *                            is active, which specialist templates appear
 *                            in the "+ Add specialist exam" picker).
 */
class CreateVcExamTables extends Migration
{
    public function up()
    {
        // ── Templates: a named bundle of exam items ──────────────────
        if (!Schema::hasTable('vc_exam_templates')) {
            Schema::create('vc_exam_templates', function (Blueprint $table) {
                $table->increments('id');
                // null = system-shipped template available to every clinic
                $table->unsignedInteger('business_id')->nullable()->index();
                $table->string('name', 120);
                // 'general'    - always-on head-to-tail exam
                // 'specialist' - opened on demand (orthopedic, neuro, derma...)
                // 'breed'      - species/breed-specific add-ons
                $table->enum('kind', ['general', 'specialist', 'breed'])->index();
                // Hint about which animals this applies to. 'all' = no filter.
                $table->string('species_scope', 30)->default('all')->index();
                // For specialist templates the doctor sees a label like
                // "Orthopedic exam" - this is what goes into the
                // "+ Add specialist exam" picker on the appointment.
                $table->string('display_label', 140)->nullable();
                $table->string('icon', 60)->nullable();  // FontAwesome class
                $table->string('colour', 12)->nullable(); // hex without #
                $table->text('description')->nullable();
                $table->boolean('is_active')->default(true)->index();
                $table->unsignedSmallInteger('sort_order')->default(0);
                $table->timestamps();
                $table->index(['business_id', 'kind', 'is_active'], 'vc_exam_tpl_lookup');
            });
        }

        // ── Items inside a template ──────────────────────────────────
        if (!Schema::hasTable('vc_exam_template_items')) {
            Schema::create('vc_exam_template_items', function (Blueprint $table) {
                $table->increments('id');
                $table->unsignedInteger('template_id')->index();
                // Group items into anatomical regions / sections for UI.
                // e.g. "General", "Eyes", "Cardiovascular", "Stifle",
                // "Cranial nerves". Same value across sibling items
                // collapses them into one accordion row in the UI.
                $table->string('region', 80)->index();
                // The actual question/label, e.g. "Mucous membrane colour".
                $table->string('item_label', 200);
                // Drives which widget renders for this item.
                //   select       - dropdown picking one of options_json
                //   multi_select - checkbox group picking many
                //   grade        - numeric scale (e.g. murmur grade I-VI)
                //   measurement  - numeric input with unit + critical bounds
                //   text         - free-text note
                //   yes_no       - boolean radio
                //   body_map     - clickable image with location pins
                //                  (UI stub in Phase A, fully wired in B)
                $table->enum('response_type', [
                    'select','multi_select','grade','measurement','text','yes_no','body_map',
                ])->default('select');
                // JSON list of options for select/multi_select/grade.
                // Each: {value, label, severity (0-3), is_critical (bool)}
                $table->json('options_json')->nullable();
                $table->string('unit', 20)->nullable();              // measurement
                $table->decimal('normal_low',  10, 3)->nullable();    // measurement
                $table->decimal('normal_high', 10, 3)->nullable();    // measurement
                $table->decimal('critical_low',  10, 3)->nullable();  // measurement
                $table->decimal('critical_high', 10, 3)->nullable();  // measurement
                $table->string('lateralisation', 12)->default('none'); // 'none'|'lr'|'ad_as'|'od_os'
                $table->boolean('is_required')->default(false);
                $table->unsignedSmallInteger('sort_order')->default(0);
                $table->text('help_text')->nullable();
                $table->timestamps();
                $table->index(['template_id', 'region', 'sort_order'], 'vc_exam_tpl_item_order');
            });
        }

        // ── Per-appointment doctor responses ─────────────────────────
        if (!Schema::hasTable('vc_appointment_exam_findings')) {
            Schema::create('vc_appointment_exam_findings', function (Blueprint $table) {
                $table->increments('id');
                $table->unsignedInteger('business_id')->index();
                $table->unsignedInteger('appointment_id')->index();
                $table->unsignedInteger('template_id')->index();
                $table->unsignedInteger('template_item_id')->index();
                // Snapshot copies so a later template edit doesn't rewrite
                // historical findings.
                $table->string('region_snapshot', 80)->nullable();
                $table->string('item_label_snapshot', 200);
                // 'left' | 'right' | 'both' | 'ad' | 'as' | 'od' | 'os' | null
                $table->string('side', 8)->nullable();
                // The actual answer - stored as text for portability, then
                // interpreted per response_type. For measurement we also
                // store the parsed numeric value separately.
                $table->text('value')->nullable();
                $table->decimal('numeric_value', 10, 3)->nullable();
                $table->json('values_json')->nullable(); // for multi_select / body_map pins
                $table->text('free_text')->nullable();
                // Severity score 0 (normal) .. 3 (severe). Computed from the
                // selected option_json entry or measurement-vs-critical
                // bounds. Drives the critical-check report (4.1).
                $table->unsignedTinyInteger('severity')->default(0)->index();
                $table->boolean('is_critical')->default(false)->index();
                $table->unsignedInteger('recorded_by')->nullable();
                $table->timestamps();
                $table->unique(['appointment_id', 'template_item_id', 'side'], 'vc_exam_finding_unique');
                $table->index(['appointment_id', 'is_critical'], 'vc_exam_finding_critical');
            });
        }

        // ── Per-business defaults for which exams are active ─────────
        if (!Schema::hasTable('vc_exam_settings')) {
            Schema::create('vc_exam_settings', function (Blueprint $table) {
                $table->increments('id');
                $table->unsignedInteger('business_id')->unique();
                // Which general template fires automatically on every new
                // appointment Objective tab. NULL = use the system default.
                $table->unsignedInteger('active_general_template_id')->nullable();
                // JSON array of specialist template ids visible in the
                // "+ Add specialist exam" picker. NULL = show all active.
                $table->json('visible_specialist_template_ids')->nullable();
                // Toggle for the smart layer (1.4 Phase C). Off by default.
                $table->boolean('enable_ai_suggest')->default(false);
                $table->boolean('enable_comparison_with_previous')->default(true);
                $table->boolean('enable_voice_fill')->default(true);
                $table->timestamps();
            });
        }

        // ── Permissions: separate template management from recording ─
        $perms = [
            'vet_clinic.manage_exam_templates',  // create/edit templates + items
            'vet_clinic.record_exam_findings',   // fill in findings per visit
            'vet_clinic.view_exam_findings',     // view-only (e.g. front desk)
        ];
        foreach ($perms as $p) {
            Permission::findOrCreate($p, 'web');
        }
    }

    public function down()
    {
        Schema::dropIfExists('vc_appointment_exam_findings');
        Schema::dropIfExists('vc_exam_template_items');
        Schema::dropIfExists('vc_exam_templates');
        Schema::dropIfExists('vc_exam_settings');

        $perms = [
            'vet_clinic.manage_exam_templates',
            'vet_clinic.record_exam_findings',
            'vet_clinic.view_exam_findings',
        ];
        Permission::whereIn('name', $perms)->delete();
    }
}
