<?php

namespace Tests\Feature;

use App\Http\Middleware\EnsurePlatformSession;
use App\Models\Branch;
use App\Models\CareUnit;
use App\Models\Department;
use App\Models\Member;
use App\Models\Organization;
use App\Models\User;
use App\Services\Care\CarePermissions;
use App\Services\Care\RosterService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CareMyShiftsAndNavPermissionsTest extends TestCase
{
    use RefreshDatabase;

    protected User $owner;

    protected Organization $organization;

    protected Branch $branch;

    protected CareUnit $unit;

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

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

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

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

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

        $department = Department::create([
            'owner_ref' => $this->owner->public_id,
            'branch_id' => $this->branch->id,
            'name' => 'Medicine',
            'type' => 'general',
            'is_active' => true,
        ]);

        $this->unit = CareUnit::create([
            'owner_ref' => $this->owner->public_id,
            'organization_id' => $this->organization->id,
            'department_id' => $department->id,
            'name' => 'Medical Ward',
            'kind' => 'inpatient',
            'is_active' => true,
        ]);
    }

    public function test_ambulance_staff_cannot_access_care_units_or_nursing_services_hub(): void
    {
        $user = User::create([
            'public_id' => 'amb-staff',
            'name' => 'Ambulance',
            'email' => 'amb@example.com',
        ]);
        $member = Member::create([
            'owner_ref' => $this->owner->public_id,
            'organization_id' => $this->organization->id,
            'user_ref' => $user->public_id,
            'role' => 'ambulance_staff',
            'branch_id' => $this->branch->id,
        ]);

        $permissions = app(CarePermissions::class);
        $this->assertFalse($permissions->can($member, 'nursing.services.view'));
        $this->assertFalse($permissions->can($member, 'inpatient.placement.view'));
        $this->assertFalse($permissions->can($member, 'admin.departments.view'));
        $this->assertTrue($permissions->can($member, 'nursing.my_shifts.view'));
        $this->assertFalse($permissions->can($member, 'nursing.station.view'));

        $this->actingAs($user)
            ->get(route('care.care-units.index'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.nursing.services'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.nursing.station'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.dashboard'))
            ->assertOk()
            ->assertDontSee('>Care units<', false)
            ->assertDontSee('>Nursing Services<', false)
            ->assertDontSee('>My care unit<', false)
            ->assertSee('My shifts', false);
    }

    public function test_staff_see_their_assigned_shifts(): void
    {
        $user = User::create([
            'public_id' => 'nurse-shifts',
            'name' => 'Nurse Ama',
            'email' => 'nurse-shifts@example.com',
        ]);
        $member = Member::create([
            'owner_ref' => $this->owner->public_id,
            'organization_id' => $this->organization->id,
            'user_ref' => $user->public_id,
            'role' => 'nurse',
            'branch_id' => $this->branch->id,
        ]);

        $roster = app(RosterService::class);
        $shifts = $roster->ensureDefaultShifts($this->organization, $this->owner->public_id);
        $day = $shifts->firstWhere('code', 'day');

        $roster->assign(
            $this->unit,
            $day,
            $member,
            now()->toDateString(),
            $this->owner->public_id,
            $this->owner->public_id,
        );

        $this->actingAs($user)
            ->get(route('care.my-shifts'))
            ->assertOk()
            ->assertSee('My shifts')
            ->assertSee('Medical Ward')
            ->assertSee('Day shift');
    }

    public function test_regular_nurse_cannot_access_nursing_services_hub(): void
    {
        $user = User::create([
            'public_id' => 'nurse-hub',
            'name' => 'Ward Nurse',
            'email' => 'nurse-hub@example.com',
        ]);
        $member = Member::create([
            'owner_ref' => $this->owner->public_id,
            'organization_id' => $this->organization->id,
            'user_ref' => $user->public_id,
            'role' => 'nurse',
            'branch_id' => $this->branch->id,
        ]);

        $permissions = app(CarePermissions::class);
        $this->assertFalse($permissions->can($member, 'nursing.services.view'));
        $this->assertFalse($permissions->can($member, 'inpatient.placement.view'));
        $this->assertFalse($permissions->can($member, 'nursing.roster.manage'));
        $this->assertTrue($permissions->can($member, 'nursing.my_shifts.view'));
        $this->assertTrue($permissions->can($member, 'nursing.station.view'));
        $this->assertTrue($permissions->can($member, 'mar.view'));
        $this->assertTrue($permissions->can($member, 'nursing.notes.manage'));
        $this->assertFalse($permissions->can($member, 'admin.departments.view'));
        $this->assertFalse($permissions->can($member, 'admin.departments.manage'));

        $this->actingAs($user)
            ->get(route('care.care-units.index'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.care-units.create'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.departments.index'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.departments.create'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.nursing.services'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.specialty.show', 'nursing_services'))
            ->assertForbidden();

        $this->actingAs($user)
            ->get(route('care.nursing.station'))
            ->assertOk()
            ->assertSee('My care unit')
            ->assertSee('No unit assigned for today');

        $this->actingAs($user)
            ->get(route('care.dashboard'))
            ->assertOk()
            ->assertDontSee('>Care units<', false)
            ->assertDontSee('>Departments<', false)
            ->assertDontSee('>Nursing Services<', false)
            ->assertDontSee('>Nursing<', false)
            ->assertSee('>My care unit<', false)
            ->assertSee('My shifts', false);
    }

    public function test_regular_nurse_station_shows_rostered_unit_patients_and_clinical_boards(): void
    {
        $user = User::create([
            'public_id' => 'nurse-station',
            'name' => 'Nurse Kojo',
            'email' => 'nurse-station@example.com',
        ]);
        $member = Member::create([
            'owner_ref' => $this->owner->public_id,
            'organization_id' => $this->organization->id,
            'user_ref' => $user->public_id,
            'role' => 'nurse',
            'branch_id' => $this->branch->id,
        ]);

        $roster = app(RosterService::class);
        $day = $roster->ensureDefaultShifts($this->organization, $this->owner->public_id)->firstWhere('code', 'day');
        $roster->assign(
            $this->unit,
            $day,
            $member,
            now()->toDateString(),
            $this->owner->public_id,
            $this->owner->public_id,
        );

        $patient = \App\Models\Patient::create([
            'owner_ref' => $this->owner->public_id,
            'organization_id' => $this->organization->id,
            'branch_id' => $this->branch->id,
            'patient_number' => 'P-WARD-1',
            'first_name' => 'Ama',
            'last_name' => 'Mensah',
        ]);
        \App\Models\Visit::create([
            'owner_ref' => $this->owner->public_id,
            'organization_id' => $this->organization->id,
            'branch_id' => $this->branch->id,
            'patient_id' => $patient->id,
            'care_unit_id' => $this->unit->id,
            'status' => \App\Models\Visit::STATUS_OPEN,
            'checked_in_at' => now(),
            'placed_at' => now(),
        ]);

        $this->actingAs($user)
            ->get(route('care.nursing.station'))
            ->assertOk()
            ->assertSee('Medical Ward')
            ->assertSee('Ama Mensah')
            ->assertSee('MAR round')
            ->assertSee('Vitals &amp; assess', false)
            ->assertSee('Notes')
            ->assertSee('Handover');

        $this->actingAs($user)
            ->get(route('care.care-units.mar', $this->unit))
            ->assertOk()
            ->assertSee('MAR board');

        $this->actingAs($user)
            ->get(route('care.care-units.notes', $this->unit))
            ->assertOk()
            ->assertSee('Nursing notes');

        $this->actingAs($user)
            ->get(route('care.care-units.assessments', $this->unit))
            ->assertOk()
            ->assertSee('Ward assessment board');

        $this->actingAs($user)
            ->get(route('care.care-units.show', $this->unit))
            ->assertOk()
            ->assertSee('Ama Mensah');

        $this->actingAs($user)
            ->get(route('care.my-shifts'))
            ->assertOk()
            ->assertSee('Open care unit');
    }
}
