<?php

namespace Tests\Feature;

use App\Http\Middleware\EnsurePlatformSession;
use App\Models\Branch;
use App\Models\Member;
use App\Models\Organization;
use App\Models\Practitioner;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CarePractitionerBranchesTest extends TestCase
{
    use RefreshDatabase;

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

        [$owner, $organization, $east, $west] = $this->seedOrg();

        $this->actingAs($owner)
            ->post(route('care.practitioners.store'), [
                'name' => 'Dr. Tele',
                'specialty' => 'General Practice',
            ])
            ->assertSessionHasErrors('branch_ids');

        $this->actingAs($owner)
            ->post(route('care.practitioners.store'), [
                'name' => 'Dr. Tele',
                'specialty' => 'General Practice',
                'branch_ids' => [$east->id, $west->id],
            ])
            ->assertRedirect(route('care.practitioners.index'));

        $practitioner = Practitioner::query()->where('name', 'Dr. Tele')->firstOrFail();
        $this->assertEqualsCanonicalizing(
            [$east->id, $west->id],
            $practitioner->assignedBranchIds(),
        );
        $this->assertSame($east->id, (int) $practitioner->branch_id);

        $this->actingAs($owner)
            ->get(route('care.practitioners.index'))
            ->assertOk()
            ->assertSee('East Legon Care')
            ->assertSee('West Hills Care')
            ->assertDontSee('All branches');
    }

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

        [$owner] = $this->seedOrg();

        $this->actingAs($owner)
            ->get(route('care.practitioners.create'))
            ->assertOk()
            ->assertSee('name="specialty"', false)
            ->assertSee('<select name="specialty"', false)
            ->assertSee('General Practice')
            ->assertSee('Dentistry')
            ->assertDontSee('placeholder="General practice"', false);
    }

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

        [$owner, $organization, $east] = $this->seedOrg();

        $this->actingAs($owner)
            ->post(route('care.practitioners.store'), [
                'name' => 'Dr. Unknown',
                'specialty' => 'Not A Real Specialty',
                'branch_ids' => [$east->id],
            ])
            ->assertSessionHasErrors('specialty');
    }

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

        [$owner, $organization, $east, $west] = $this->seedOrg();

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

        $doctor = User::create([
            'public_id' => 'multi-branch-doc',
            'name' => 'Tele Doctor',
            'email' => 'tele-doc@example.com',
        ]);
        $member = Member::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'user_ref' => $doctor->public_id,
            'role' => 'doctor',
            'branch_id' => $east->id,
        ]);
        $practitioner = Practitioner::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'branch_id' => $east->id,
            'member_id' => $member->id,
            'user_ref' => $doctor->public_id,
            'name' => 'Tele Doctor',
            'is_active' => true,
        ]);
        $practitioner->syncAssignedBranches([$east->id, $west->id]);

        $this->actingAs($doctor)
            ->get(route('care.queue.index'))
            ->assertOk()
            ->assertSee('Assigned to you')
            ->assertSee('name="branch_id"', false)
            ->assertSee('East Legon Care')
            ->assertSee('West Hills Care')
            ->assertDontSee('Airport Clinic');

        $this->actingAs($doctor)
            ->get(route('care.queue.index', ['branch_id' => $west->id]))
            ->assertOk()
            ->assertSee('West Hills Care');

        $this->actingAs($doctor)
            ->get(route('care.queue.index', ['branch_id' => $other->id]))
            ->assertOk()
            ->assertDontSee('Airport Clinic');
    }

    /**
     * @return array{0: User, 1: Organization, 2: Branch, 3: Branch}
     */
    protected function seedOrg(): array
    {
        $owner = User::create([
            'public_id' => 'prac-branch-owner',
            'name' => 'Owner',
            'email' => 'prac-owner@example.com',
        ]);

        $organization = Organization::create([
            'owner_ref' => $owner->public_id,
            'name' => 'Multi Site Clinic',
            'slug' => 'multi-site-clinic',
            'timezone' => 'UTC',
            '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',
            'branch_id' => null,
        ]);

        $east = Branch::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'name' => 'East Legon Care',
            'is_active' => true,
        ]);

        $west = Branch::create([
            'owner_ref' => $owner->public_id,
            'organization_id' => $organization->id,
            'name' => 'West Hills Care',
            'is_active' => true,
        ]);

        return [$owner, $organization, $east, $west];
    }
}
