<?php

namespace Tests\Feature;

use App\Http\Middleware\EnsurePlatformSession;
use App\Models\Assessment;
use App\Models\AssessmentScore;
use App\Models\AssessmentTemplate;
use App\Models\Branch;
use App\Models\ClinicalPathway;
use App\Models\Consultation;
use App\Models\Diagnosis;
use App\Models\Member;
use App\Models\Organization;
use App\Models\Patient;
use App\Models\PatientPathway;
use App\Models\User;
use App\Models\Visit;
use App\Services\Care\CareFeatures;
use App\Services\Care\ScoringService;
use Database\Seeders\AssessmentTemplateSeeder;
use Database\Seeders\ClinicalPathwaySeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Str;
use Tests\TestCase;

/**
 * PR 6 — Stroke MVP content packs (NIHSS + mRS) and M2 vertical slice.
 */
class CareStrokeMvpTest extends TestCase
{
    use RefreshDatabase;

    protected User $user;

    protected Organization $organization;

    protected Branch $branch;

    protected Patient $patient;

    protected Member $member;

    protected function setUp(): void
    {
        parent::setUp();
        $this->withoutMiddleware(EnsurePlatformSession::class);

        $this->user = User::create([
            'public_id' => 'stroke-mvp-user',
            'name' => 'Stroke MVP',
            'email' => 'stroke@example.com',
        ]);

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

        $this->member = 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-STROKE-001',
            'first_name' => 'Efua',
            'last_name' => 'Asante',
        ]);

        $this->seed(AssessmentTemplateSeeder::class);
        $this->seed(ClinicalPathwaySeeder::class);
    }

    public function test_seed_packs_load_nihss_and_mrs(): void
    {
        $nihss = AssessmentTemplate::currentSystemByCode('nihss');
        $mrs = AssessmentTemplate::currentSystemByCode('mrs');

        $this->assertNotNull($nihss);
        $this->assertNotNull($mrs);
        $this->assertSame('sum_items', $nihss->scoring_strategy);
        $this->assertSame('single_value', $mrs->scoring_strategy);
        $this->assertSame(15, $nihss->questions()->count());
        $this->assertSame(1, $mrs->questions()->count());
        $this->assertSame(['doctor'], $nihss->meta['capture_roles'] ?? null);

        $pathway = ClinicalPathway::findByCode('stroke');
        $this->assertNotNull($pathway);
        $codes = $pathway->templates()->pluck('template_code')->all();
        $this->assertContains('nihss', $codes);
        $this->assertContains('mrs', $codes);
        $required = $pathway->templates()->where('is_required_on_activation', true)->pluck('template_code')->all();
        $this->assertEqualsCanonicalizing(['nihss', 'mrs'], $required);
    }

    public function test_golden_mrs_score_three(): void
    {
        $this->actingAs($this->user)
            ->post(route('care.assessments.store', $this->patient), ['template_code' => 'mrs'])
            ->assertRedirect();

        $assessment = Assessment::first();
        $this->actingAs($this->user)
            ->put(route('care.assessments.update', $assessment), [
                'answers' => ['mrs_score' => '3'],
            ])
            ->assertRedirect();

        $this->actingAs($this->user)
            ->post(route('care.assessments.complete', $assessment))
            ->assertRedirect();

        $score = AssessmentScore::where('assessment_id', $assessment->id)->first();
        $this->assertNotNull($score);
        $this->assertEquals(3, (float) $score->total_score);
        $this->assertEquals(6, (float) $score->max_score);
        $this->assertSame('mrs', $score->template_code);
    }

    public function test_golden_nihss_fixture_total_twelve_max_forty_two(): void
    {
        // Moderate left hemisphere pattern → total 12; max 42.
        $answers = [
            '1a_loc' => '1',
            '1b_loc_questions' => '1',
            '1c_loc_commands' => '0',
            '2_gaze' => '0',
            '3_visual' => '1',
            '4_facial' => '2',
            '5a_motor_arm_left' => '2',
            '5b_motor_arm_right' => '0',
            '6a_motor_leg_left' => '2',
            '6b_motor_leg_right' => '0',
            '7_ataxia' => '0',
            '8_sensory' => '1',
            '9_language' => '1',
            '10_dysarthria' => '1',
            '11_extinction' => '0',
        ];
        // 1+1+0+0+1+2+2+0+2+0+0+1+1+1+0 = 12

        $this->actingAs($this->user)
            ->post(route('care.assessments.store', $this->patient), ['template_code' => 'nihss'])
            ->assertRedirect();

        $assessment = Assessment::first();
        $this->actingAs($this->user)
            ->put(route('care.assessments.update', $assessment), ['answers' => $answers])
            ->assertRedirect();

        $preview = app(ScoringService::class)->preview(
            $assessment->fresh(['template.questions', 'answers.question'])
        );
        $this->assertEquals(12.0, $preview['total']);
        $this->assertEquals(42.0, $preview['max']);

        $this->actingAs($this->user)
            ->post(route('care.assessments.complete', $assessment))
            ->assertRedirect();

        $score = AssessmentScore::first();
        $this->assertEquals(12, (float) $score->total_score);
        $this->assertEquals(42, (float) $score->max_score);
        $this->assertArrayHasKey('loc', $score->subscores);
        $this->assertEquals(2.0, (float) $score->subscores['loc']); // 1a+1b+1c = 2
    }

    public function test_m2_e2e_activate_stroke_complete_nihss_and_mrs(): void
    {
        $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(),
        ]);

        Diagnosis::create([
            'owner_ref' => $this->user->public_id,
            'consultation_id' => $consultation->id,
            'code' => 'I63.9',
            'description' => 'Cerebral infarction, unspecified',
            'is_primary' => true,
        ]);

        $this->actingAs($this->user)
            ->get(route('care.consultations.show', $consultation))
            ->assertOk()
            ->assertSee('Stroke')
            ->assertSee('Activate');

        $this->actingAs($this->user)
            ->post(route('care.pathways.store', $this->patient), [
                'pathway_code' => 'stroke',
                'consultation_uuid' => $consultation->uuid,
            ])
            ->assertRedirect();

        $this->assertSame(1, PatientPathway::where('status', PatientPathway::STATUS_ACTIVE)->count());
        $this->assertSame(2, Assessment::where('status', Assessment::STATUS_DRAFT)->count());

        $this->actingAs($this->user)
            ->get(route('care.consultations.show', $consultation))
            ->assertOk()
            ->assertSee('Recommended forms')
            ->assertSee('NIH Stroke Scale')
            ->assertSee('Modified Rankin Scale')
            ->assertSee('Continue');

        $nihss = Assessment::query()
            ->whereHas('template', fn ($q) => $q->where('code', 'nihss'))
            ->first();
        $mrs = Assessment::query()
            ->whereHas('template', fn ($q) => $q->where('code', 'mrs'))
            ->first();

        $this->assertNotNull($nihss);
        $this->assertNotNull($mrs);
        $this->assertSame($consultation->id, $nihss->consultation_id);

        // Minimal valid NIHSS (all zeros) → total 0.
        $zeroAnswers = collect($nihss->template->questions)->mapWithKeys(
            fn ($q) => [$q->code => '0']
        )->all();

        $this->actingAs($this->user)
            ->put(route('care.assessments.update', $nihss), ['answers' => $zeroAnswers])
            ->assertRedirect();
        $this->actingAs($this->user)
            ->post(route('care.assessments.complete', $nihss))
            ->assertRedirect();

        $this->assertEquals(0, (float) AssessmentScore::where('assessment_id', $nihss->id)->value('total_score'));
        $this->assertEquals(42, (float) AssessmentScore::where('assessment_id', $nihss->id)->value('max_score'));

        $this->actingAs($this->user)
            ->put(route('care.assessments.update', $mrs), ['answers' => ['mrs_score' => '2']])
            ->assertRedirect();
        $this->actingAs($this->user)
            ->post(route('care.assessments.complete', $mrs))
            ->assertRedirect();

        $this->assertEquals(2, (float) AssessmentScore::where('assessment_id', $mrs->id)->value('total_score'));

        $this->actingAs($this->user)
            ->get(route('care.consultations.show', $consultation))
            ->assertOk()
            ->assertSee('score 0')
            ->assertSee('score 2');
    }

    public function test_nurse_cannot_start_seeded_nihss(): void
    {
        $this->member->update(['role' => 'nurse']);

        $this->actingAs($this->user)
            ->post(route('care.assessments.store', $this->patient), ['template_code' => 'nihss'])
            ->assertForbidden();
    }
}
