<?php

namespace Tests\Feature;

use App\Domain\Clinical\ToothChartService;
use App\Enums\ToothState;
use App\Models\Patient;
use App\Models\Tenant;
use App\Models\ToothRecord;
use App\Models\User;
use App\Support\Tenancy;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ToothChartTest extends TestCase
{
    use RefreshDatabase;

    protected Tenant $tenant;
    protected Patient $patient;
    protected User $dentistUser;
    protected string $base;

    protected function setUp(): void
    {
        parent::setUp();
        $this->seed();

        $this->tenant = Tenant::create(['name' => 'Smile', 'slug' => 'smile']);
        $this->tenant->subscription()->create([
            'plan_id' => \App\Models\Plan::first()->id, 'status' => 'trialing',
            'starts_at' => now(), 'current_period_ends_at' => now()->addDays(14),
        ]);

        app(Tenancy::class)->set($this->tenant);
        $this->patient = Patient::factory()->create();
        $this->dentistUser = User::withoutEvents(fn () => User::create([
            'tenant_id' => $this->tenant->id, 'name' => 'Dr', 'email' => 'd@x.com', 'password' => 'password123',
        ]));
        $this->dentistUser->assignRole('dentist');
        app(Tenancy::class)->forget();

        $this->base = 'http://smile.'.config('tenancy.central_domain');
    }

    public function test_chart_has_all_32_fdi_teeth(): void
    {
        app(Tenancy::class)->set($this->tenant);
        $chart = app(ToothChartService::class)->chartFor($this->patient);

        $this->assertCount(32, $chart);
        foreach ([11, 18, 21, 28, 31, 38, 41, 48] as $tooth) {
            $this->assertArrayHasKey($tooth, $chart);
        }
        $this->assertArrayNotHasKey(19, $chart->toArray());
    }

    public function test_recording_a_finding_with_surfaces(): void
    {
        $this->actingAs($this->dentistUser)
            ->postJson($this->base.'/patients/'.$this->patient->id.'/chart', [
                'tooth' => 16, 'condition' => 'caries', 'state' => 'existing',
                'surfaces' => ['M', 'O'], 'note' => 'Deep caries',
            ])->assertCreated()
            ->assertJsonPath('data.surfaces', ['M', 'O']);

        app(Tenancy::class)->set($this->tenant);
        $chart = app(ToothChartService::class)->chartFor($this->patient);
        $this->assertSame('caries', $chart[16]['condition']);
        $this->assertNull($chart[11]['condition']);
    }

    public function test_invalid_fdi_number_is_rejected(): void
    {
        $this->actingAs($this->dentistUser)
            ->postJson($this->base.'/patients/'.$this->patient->id.'/chart', [
                'tooth' => 19, 'condition' => 'caries', 'state' => 'existing',
            ])->assertUnprocessable();
    }

    public function test_history_is_ordered_newest_first_and_current_wins(): void
    {
        app(Tenancy::class)->set($this->tenant);
        $svc = app(ToothChartService::class);

        $svc->record($this->patient, 16, 'caries', ToothState::Existing);
        ToothRecord::query()->update(['recorded_at' => now()->subDay()]);
        $svc->record($this->patient, 16, 'filling', ToothState::Completed);

        $chart = $svc->chartFor($this->patient);
        $this->assertSame('filling', $chart[16]['condition']);
        $this->assertCount(2, $chart[16]['records']);
        $this->assertSame('filling', $chart[16]['records'][0]['condition']);
    }

    public function test_planned_records_do_not_override_current_condition(): void
    {
        app(Tenancy::class)->set($this->tenant);
        $svc = app(ToothChartService::class);

        $svc->record($this->patient, 26, 'caries', ToothState::Existing);
        $svc->record($this->patient, 26, 'crown', ToothState::Planned);

        $chart = $svc->chartFor($this->patient);
        $this->assertSame('caries', $chart[26]['condition']);
        $this->assertTrue($chart[26]['has_planned']);
    }

    public function test_receptionist_cannot_record_findings(): void
    {
        app(Tenancy::class)->set($this->tenant);
        $reception = User::withoutEvents(fn () => User::create([
            'tenant_id' => $this->tenant->id, 'name' => 'R', 'email' => 'r@x.com', 'password' => 'password123',
        ]));
        $reception->assignRole('receptionist');
        app(Tenancy::class)->forget();

        $this->actingAs($reception)
            ->postJson($this->base.'/patients/'.$this->patient->id.'/chart', [
                'tooth' => 16, 'condition' => 'caries', 'state' => 'existing',
            ])->assertForbidden();
    }
}
