<?php

namespace Tests\Feature;

use App\Http\Middleware\EnsurePlatformSession;
use App\Models\Appointment;
use App\Models\Branch;
use App\Models\Department;
use App\Models\Member;
use App\Models\Organization;
use App\Models\Patient;
use App\Models\User;
use App\Models\Visit;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\SpecialtyModuleService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CareNurseOrgAccessTest extends TestCase
{
    use RefreshDatabase;

    public function test_nurse_with_email_user_ref_membership_is_not_sent_to_onboarding(): void
    {
        $this->withoutMiddleware(EnsurePlatformSession::class);

        $owner = User::create([
            'public_id' => 'owner-pid',
            'name' => 'Owner',
            'email' => 'owner@example.com',
        ]);

        $nurse = User::create([
            'public_id' => 'nurse-pid',
            'name' => 'Nurse',
            'email' => 'demo-pro-nurse@ladill.com',
        ]);

        $organization = Organization::create([
            'owner_ref' => $owner->public_id,
            'name' => 'Clinic',
            'slug' => 'clinic',
            'settings' => [
                'onboarded' => true,
                'plan' => 'pro',
                'plan_expires_at' => now()->addMonth()->toIso8601String(),
            ],
        ]);

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

        // Demo seeder style: staff member keyed by email until SSO remaps.
        Member::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'user_ref' => strtolower($nurse->email),
            'role' => 'nurse',
        ]);

        $resolver = app(OrganizationResolver::class);
        $this->assertTrue($resolver->isOnboarded($nurse));
        $this->assertFalse($resolver->canCompleteOnboarding($nurse));
        $this->assertSame($organization->id, $resolver->resolveForUser($nurse)?->id);

        // Remap sticks so later requests resolve by public_id.
        $this->assertDatabaseHas('care_members', [
            'organization_id' => $organization->id,
            'user_ref' => $nurse->public_id,
            'role' => 'nurse',
        ]);

        $this->actingAs($nurse)
            ->get(route('care.dashboard'))
            ->assertOk();

        $this->actingAs($nurse)
            ->get(route('care.onboarding.show'))
            ->assertRedirect(route('care.dashboard'));
    }

    public function test_nurse_who_wrongly_owns_empty_org_still_uses_employer_membership(): void
    {
        $this->withoutMiddleware(EnsurePlatformSession::class);

        $owner = User::create([
            'public_id' => 'employer-owner',
            'name' => 'Owner',
            'email' => 'employer@example.com',
        ]);

        $nurse = User::create([
            'public_id' => 'orphan-nurse',
            'name' => 'Nurse',
            'email' => 'orphan-nurse@example.com',
        ]);

        $employer = Organization::create([
            'owner_ref' => $owner->public_id,
            'name' => 'Employer Clinic',
            'slug' => 'employer-clinic',
            'settings' => [
                'onboarded' => true,
                'plan' => 'pro',
                'plan_expires_at' => now()->addMonth()->toIso8601String(),
                'specialty_modules' => ['emergency' => true],
            ],
        ]);

        // Orphan org from completing owner onboarding while membership was unresolved.
        Organization::create([
            'owner_ref' => $nurse->public_id,
            'name' => 'Nurse Own Clinic',
            'slug' => 'nurse-own-clinic',
            'settings' => ['onboarded' => true],
        ]);

        Member::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $employer->id,
            'user_ref' => strtolower($nurse->email),
            'role' => 'ed_nurse',
        ]);

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

        app(SpecialtyModuleService::class)->activate($employer, $owner->public_id, 'emergency');
        $dept = Department::query()->where('type', 'emergency')->where('branch_id', $branch->id)->firstOrFail();

        $patient = Patient::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $employer->id,
            'branch_id' => $branch->id,
            'patient_number' => 'P-ORPHAN',
            'first_name' => 'Ama',
            'last_name' => 'Patient',
            'gender' => 'female',
            'date_of_birth' => '1990-01-01',
        ]);

        $visit = Visit::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $employer->id,
            'branch_id' => $branch->id,
            'patient_id' => $patient->id,
            'status' => Visit::STATUS_IN_PROGRESS,
            'checked_in_at' => now(),
        ]);

        Appointment::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $employer->id,
            'branch_id' => $branch->id,
            'patient_id' => $patient->id,
            'department_id' => $dept->id,
            'visit_id' => $visit->id,
            'type' => Appointment::TYPE_WALK_IN,
            'status' => Appointment::STATUS_IN_CONSULTATION,
            'scheduled_at' => now(),
            'checked_in_at' => now(),
            'started_at' => now(),
        ]);

        $this->assertSame($employer->id, app(OrganizationResolver::class)->resolveForUser($nurse)?->id);

        $this->actingAs($nurse)
            ->get(route('care.specialty.workspace', [
                'module' => 'emergency',
                'visit' => $visit,
                'tab' => 'documents',
            ]))
            ->assertOk()
            ->assertSee('Documents')
            ->assertSee('Upload document');
    }

    public function test_nurse_can_open_emergency_documents_tab(): void
    {
        $this->withoutMiddleware(EnsurePlatformSession::class);

        $owner = User::create([
            'public_id' => 'er-docs-owner',
            'name' => 'Owner',
            'email' => 'er-docs-owner@example.com',
        ]);

        $nurse = User::create([
            'public_id' => 'er-docs-nurse',
            'name' => 'ED Nurse',
            'email' => 'er-docs-nurse@example.com',
        ]);

        $organization = Organization::create([
            'owner_ref' => $owner->public_id,
            'name' => 'ER Clinic',
            'slug' => 'er-docs-clinic',
            'settings' => [
                'onboarded' => true,
                'plan' => 'pro',
                'plan_expires_at' => now()->addMonth()->toIso8601String(),
                'specialty_modules' => ['emergency' => true],
            ],
        ]);

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

        Member::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'user_ref' => $nurse->public_id,
            'role' => 'ed_nurse',
        ]);

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

        app(SpecialtyModuleService::class)->activate($organization, $owner->public_id, 'emergency');

        $dept = Department::query()->where('type', 'emergency')->where('branch_id', $branch->id)->firstOrFail();

        $patient = Patient::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'branch_id' => $branch->id,
            'patient_number' => 'P-DOCS',
            'first_name' => 'Ama',
            'last_name' => 'Docs',
            'gender' => 'female',
            'date_of_birth' => '1990-01-01',
        ]);

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

        Appointment::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'branch_id' => $branch->id,
            'patient_id' => $patient->id,
            'department_id' => $dept->id,
            'visit_id' => $visit->id,
            'type' => Appointment::TYPE_WALK_IN,
            'status' => Appointment::STATUS_IN_CONSULTATION,
            'scheduled_at' => now(),
            'checked_in_at' => now(),
            'started_at' => now(),
        ]);

        $this->actingAs($nurse)
            ->get(route('care.specialty.workspace', [
                'module' => 'emergency',
                'visit' => $visit,
                'tab' => 'documents',
            ]))
            ->assertOk()
            ->assertSee('Documents')
            ->assertSee('Upload document');
    }

    public function test_view_only_staff_sees_documents_without_upload(): void
    {
        $this->withoutMiddleware(EnsurePlatformSession::class);

        $owner = User::create([
            'public_id' => 'view-docs-owner',
            'name' => 'Owner',
            'email' => 'view-docs-owner@example.com',
        ]);

        $lab = User::create([
            'public_id' => 'view-docs-lab',
            'name' => 'Lab',
            'email' => 'view-docs-lab@example.com',
        ]);

        $organization = Organization::create([
            'owner_ref' => $owner->public_id,
            'name' => 'Rad Clinic',
            'slug' => 'rad-docs-clinic',
            'settings' => [
                'onboarded' => true,
                'plan' => 'pro',
                'plan_expires_at' => now()->addMonth()->toIso8601String(),
            ],
        ]);

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

        Member::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'user_ref' => $lab->public_id,
            'role' => 'lab_technician',
        ]);

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

        $modules = app(SpecialtyModuleService::class);
        $modules->activate($organization, $owner->public_id, 'radiology');

        $dept = Department::query()->where('type', 'radiology')->where('branch_id', $branch->id)->firstOrFail();

        $patient = Patient::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'branch_id' => $branch->id,
            'patient_number' => 'P-VIEW-DOCS',
            'first_name' => 'Kofi',
            'last_name' => 'View',
            'gender' => 'male',
            'date_of_birth' => '1985-01-01',
        ]);

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

        Appointment::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'branch_id' => $branch->id,
            'patient_id' => $patient->id,
            'department_id' => $dept->id,
            'visit_id' => $visit->id,
            'type' => Appointment::TYPE_WALK_IN,
            'status' => Appointment::STATUS_IN_CONSULTATION,
            'scheduled_at' => now(),
            'checked_in_at' => now(),
            'started_at' => now(),
        ]);

        $labMember = Member::query()->where('user_ref', $lab->public_id)->firstOrFail();
        // Lab manages pathology/blood bank; radiology is view-only.
        $this->assertSame('view', $modules->memberAccessLevel($organization, $labMember, 'radiology'));

        $this->actingAs($lab)
            ->get(route('care.specialty.workspace', [
                'module' => 'radiology',
                'visit' => $visit,
                'tab' => 'documents',
            ]))
            ->assertOk()
            ->assertSee('Documents')
            ->assertDontSee('Upload document');
    }
}
