<?php

namespace Tests\Feature;

use App\Models\Assessment;
use App\Models\AssessmentAnswer;
use App\Models\AssessmentQuestion;
use App\Models\AssessmentTemplate;
use App\Models\Branch;
use App\Models\Consultation;
use App\Models\Member;
use App\Models\Organization;
use App\Models\Patient;
use App\Models\User;
use App\Models\Visit;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Str;
use Tests\TestCase;

/**
 * PR 1 — schema, models, relations, catalog uniqueness (no service/UI yet).
 */
class CareAssessmentEngineTest extends TestCase
{
    use RefreshDatabase;

    protected User $user;

    protected Organization $organization;

    protected Branch $branch;

    protected Patient $patient;

    protected function setUp(): void
    {
        parent::setUp();

        $this->user = User::create([
            'public_id' => 'test-user-assess-001',
            'name' => 'Assessment Test User',
            'email' => 'assess@example.com',
        ]);

        $this->organization = Organization::create([
            'owner_ref' => $this->user->public_id,
            'name' => 'Assess Clinic',
            'slug' => 'assess-clinic',
            'timezone' => 'UTC',
            'settings' => ['onboarded' => true],
        ]);

        Member::create([
            'owner_ref' => $this->user->public_id,
            'organization_id' => $this->organization->id,
            'user_ref' => $this->user->public_id,
            'role' => 'doctor',
        ]);

        $this->branch = Branch::create([
            'owner_ref' => $this->user->public_id,
            'organization_id' => $this->organization->id,
            'name' => 'Main',
            'is_active' => true,
        ]);

        $this->patient = Patient::create([
            'uuid' => (string) Str::uuid(),
            'owner_ref' => $this->user->public_id,
            'organization_id' => $this->organization->id,
            'branch_id' => $this->branch->id,
            'patient_number' => 'LC-2026-ASSESS-001',
            'first_name' => 'Ama',
            'last_name' => 'Mensah',
        ]);
    }

    public function test_template_auto_generates_uuid_and_has_no_owner_ref(): void
    {
        $template = AssessmentTemplate::create([
            'code' => 'universal_intake',
            'name' => 'Universal Intake',
            'category' => AssessmentTemplate::CATEGORY_UNIVERSAL,
            'version' => 1,
            'is_current' => true,
            'is_active' => true,
            'meta' => ['capture_roles' => ['nurse', 'doctor']],
        ]);

        $this->assertNotEmpty($template->uuid);
        $this->assertTrue(Str::isUuid($template->uuid));
        $this->assertNull($template->organization_id);
        $this->assertFalse(isset($template->getAttributes()['owner_ref']));
        $this->assertSame(['capture_roles' => ['nurse', 'doctor']], $template->meta);
        $this->assertSame('uuid', $template->getRouteKeyName());
    }

    public function test_system_template_code_version_is_unique(): void
    {
        AssessmentTemplate::create([
            'code' => 'nihss',
            'name' => 'NIHSS v1',
            'category' => AssessmentTemplate::CATEGORY_DISEASE,
            'version' => 1,
            'is_current' => true,
        ]);

        $this->expectException(QueryException::class);

        AssessmentTemplate::create([
            'code' => 'nihss',
            'name' => 'NIHSS v1 duplicate',
            'category' => AssessmentTemplate::CATEGORY_DISEASE,
            'version' => 1,
            'is_current' => false,
        ]);
    }

    public function test_same_code_different_versions_allowed(): void
    {
        AssessmentTemplate::create([
            'code' => 'mrs',
            'name' => 'mRS v1',
            'category' => AssessmentTemplate::CATEGORY_DISEASE,
            'version' => 1,
            'is_current' => false,
        ]);

        $v2 = AssessmentTemplate::create([
            'code' => 'mrs',
            'name' => 'mRS v2',
            'category' => AssessmentTemplate::CATEGORY_DISEASE,
            'version' => 2,
            'is_current' => true,
        ]);

        $this->assertSame(2, AssessmentTemplate::where('code', 'mrs')->count());
        $this->assertTrue($v2->is_current);
        $this->assertSame($v2->id, AssessmentTemplate::currentSystemByCode('mrs')?->id);
    }

    public function test_question_unique_per_template_and_ordered_relation(): void
    {
        $template = AssessmentTemplate::create([
            'code' => 'fixture_scale',
            'name' => 'Fixture',
            'category' => AssessmentTemplate::CATEGORY_SCREENING,
            'version' => 1,
            'is_current' => true,
        ]);

        AssessmentQuestion::create([
            'template_id' => $template->id,
            'code' => 'item_b',
            'label' => 'Item B',
            'answer_type' => AssessmentQuestion::TYPE_SCORE_ITEM,
            'sort_order' => 2,
            'is_required' => true,
        ]);

        AssessmentQuestion::create([
            'template_id' => $template->id,
            'code' => 'item_a',
            'label' => 'Item A',
            'answer_type' => AssessmentQuestion::TYPE_SCORE_ITEM,
            'sort_order' => 1,
            'is_required' => true,
        ]);

        $codes = $template->questions()->pluck('code')->all();
        $this->assertSame(['item_a', 'item_b'], $codes);

        $this->expectException(QueryException::class);
        AssessmentQuestion::create([
            'template_id' => $template->id,
            'code' => 'item_a',
            'label' => 'Duplicate',
            'answer_type' => AssessmentQuestion::TYPE_TEXT,
            'sort_order' => 3,
        ]);
    }

    public function test_assessment_instance_relations_and_owned_scope(): void
    {
        $template = AssessmentTemplate::create([
            'code' => 'universal_intake',
            'name' => 'Universal Intake',
            'category' => AssessmentTemplate::CATEGORY_UNIVERSAL,
            'version' => 1,
            'is_current' => true,
        ]);

        $question = AssessmentQuestion::create([
            'template_id' => $template->id,
            'code' => 'chief_complaint',
            'label' => 'Chief complaint',
            'answer_type' => AssessmentQuestion::TYPE_TEXT,
            'sort_order' => 1,
            'is_required' => true,
        ]);

        $visit = Visit::create([
            'owner_ref' => $this->user->public_id,
            'organization_id' => $this->organization->id,
            'branch_id' => $this->branch->id,
            'patient_id' => $this->patient->id,
            'status' => Visit::STATUS_OPEN,
            'checked_in_at' => now(),
        ]);

        $consultation = Consultation::create([
            'owner_ref' => $this->user->public_id,
            'visit_id' => $visit->id,
            'patient_id' => $this->patient->id,
            'status' => Consultation::STATUS_DRAFT,
            'started_at' => now(),
        ]);

        $assessment = Assessment::create([
            'owner_ref' => $this->user->public_id,
            'organization_id' => $this->organization->id,
            'branch_id' => $this->branch->id,
            'patient_id' => $this->patient->id,
            'template_id' => $template->id,
            'consultation_id' => $consultation->id,
            'visit_id' => $visit->id,
            'status' => Assessment::STATUS_DRAFT,
            'started_by' => $this->user->public_id,
        ]);

        $this->assertNotEmpty($assessment->uuid);
        $this->assertTrue(Str::isUuid($assessment->uuid));
        $this->assertTrue($assessment->isDraft());
        $this->assertFalse($assessment->isCompleted());

        AssessmentAnswer::create([
            'owner_ref' => $this->user->public_id,
            'assessment_id' => $assessment->id,
            'question_id' => $question->id,
            'value_text' => 'Headache for 2 days',
        ]);

        $this->assertSame(1, $assessment->answers()->count());
        $this->assertSame('Headache for 2 days', $assessment->answers->first()->authoritativeValue());
        $this->assertTrue($this->patient->assessments->contains($assessment));
        $this->assertTrue($consultation->assessments->contains($assessment));
        $this->assertTrue($visit->assessments->contains($assessment));
        $this->assertSame($template->id, $assessment->template->id);

        $this->assertSame(1, Assessment::query()->owned($this->user->public_id)->count());
        $this->assertSame(0, Assessment::query()->owned('other-owner')->count());
    }

    public function test_answer_unique_per_assessment_and_question(): void
    {
        $template = AssessmentTemplate::create([
            'code' => 'fixture',
            'name' => 'Fixture',
            'category' => AssessmentTemplate::CATEGORY_UNIVERSAL,
            'version' => 1,
            'is_current' => true,
        ]);

        $question = AssessmentQuestion::create([
            'template_id' => $template->id,
            'code' => 'pain_score',
            'label' => 'Pain',
            'answer_type' => AssessmentQuestion::TYPE_NUMBER,
            'sort_order' => 1,
        ]);

        $assessment = Assessment::create([
            'owner_ref' => $this->user->public_id,
            'organization_id' => $this->organization->id,
            'branch_id' => $this->branch->id,
            'patient_id' => $this->patient->id,
            'template_id' => $template->id,
            'status' => Assessment::STATUS_DRAFT,
        ]);

        AssessmentAnswer::create([
            'owner_ref' => $this->user->public_id,
            'assessment_id' => $assessment->id,
            'question_id' => $question->id,
            'value_number' => 5,
        ]);

        $this->expectException(QueryException::class);
        AssessmentAnswer::create([
            'owner_ref' => $this->user->public_id,
            'assessment_id' => $assessment->id,
            'question_id' => $question->id,
            'value_number' => 7,
        ]);
    }

    public function test_deleting_assessment_cascades_answers_but_not_template(): void
    {
        $template = AssessmentTemplate::create([
            'code' => 'cascade_fixture',
            'name' => 'Cascade',
            'category' => AssessmentTemplate::CATEGORY_UNIVERSAL,
            'version' => 1,
            'is_current' => true,
        ]);

        $question = AssessmentQuestion::create([
            'template_id' => $template->id,
            'code' => 'q1',
            'label' => 'Q1',
            'answer_type' => AssessmentQuestion::TYPE_BOOLEAN,
            'sort_order' => 1,
        ]);

        $assessment = Assessment::create([
            'owner_ref' => $this->user->public_id,
            'organization_id' => $this->organization->id,
            'patient_id' => $this->patient->id,
            'template_id' => $template->id,
            'status' => Assessment::STATUS_DRAFT,
        ]);

        AssessmentAnswer::create([
            'owner_ref' => $this->user->public_id,
            'assessment_id' => $assessment->id,
            'question_id' => $question->id,
            'value_boolean' => true,
        ]);

        $assessmentId = $assessment->id;
        $assessment->forceDelete();

        $this->assertDatabaseMissing('care_assessments', ['id' => $assessmentId]);
        $this->assertDatabaseMissing('care_assessment_answers', ['assessment_id' => $assessmentId]);
        $this->assertDatabaseHas('care_assessment_templates', ['id' => $template->id]);
        $this->assertDatabaseHas('care_assessment_questions', ['id' => $question->id]);
    }
}
