<?php

namespace Tests\Feature;

use App\Filament\Tenant\Pages\CalendarBoard;
use App\Models\Central\Company;
use App\Models\Central\Plan;
use App\Models\Tenant\Appointment;
use App\Models\Tenant\Client;
use App\Models\Tenant\Post;
use App\Models\Tenant\User;
use App\Models\Tenant\Vehicle;
use App\Tenancy\TenantManager;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Livewire\Livewire;
use Tests\TestCase;

class CalendarBoardV2Test extends TestCase
{
    use RefreshDatabase;

    private Company $company;
    private string $monday;

    protected function setUp(): void
    {
        parent::setUp();
        $plan = Plan::firstOrCreate(['slug' => 'test'], ['name' => 'T', 'price' => 0, 'features' => []]);
        $this->company = Company::create([
            'plan_id' => $plan->id, 'slug' => 'cv-' . uniqid(),
            'name' => 'CV Co', 'status' => 'active',
        ]);
        app(TenantManager::class)->setCurrent($this->company);
        $this->monday = Carbon::now()->startOfWeek()->toDateString();
    }

    public function test_get_days_returns_7_days_with_today_flagged(): void
    {
        $page = new CalendarBoard;
        $page->weekStart = $this->monday;
        $days = $page->getDays();

        $this->assertCount(7, $days);
        $this->assertEquals('Luni', $days[0]['name']);
        $this->assertEquals('Duminică', $days[6]['name']);
        $this->assertTrue($days[6]['is_closed']);
        $this->assertTrue($days[5]['is_weekend']);

        $todayMatches = array_filter($days, fn ($d) => $d['date'] === today()->toDateString());
        $this->assertCount(1, $todayMatches);
    }

    public function test_get_rows_returns_posts_when_grouped_by_post(): void
    {
        Post::create(['name' => 'Pod 1', 'color' => '#3B82F6', 'is_active' => true, 'hours_per_day' => 10]);
        Post::create(['name' => 'Pod 2', 'color' => '#EF4444', 'is_active' => true, 'hours_per_day' => 8]);

        $page = new CalendarBoard;
        $page->groupBy = 'post';
        $rows = $page->getRows();

        $this->assertCount(2, $rows);
        $this->assertEquals('post', $rows[0]['kind']);
        $this->assertEquals('Pod 1', $rows[0]['name']);
        $this->assertEquals(10.0, $rows[0]['capacity_hours']);
    }

    public function test_get_rows_returns_masters_plus_fallback_when_grouped_by_master(): void
    {
        $user = User::create(['name' => 'Vasile I.', 'email' => 'v@example.com', 'password' => bcrypt('x'), 'role' => 'master', 'status' => 'active', 'color' => '#F59E0B', 'specialization' => 'Motor']);

        $page = new CalendarBoard;
        $page->groupBy = 'master';
        $rows = $page->getRows();

        $this->assertGreaterThanOrEqual(2, count($rows));
        // First is the user
        $this->assertEquals('master', $rows[0]['kind']);
        $this->assertEquals('Vasile I.', $rows[0]['name']);
        $this->assertEquals('#F59E0B', $rows[0]['color']);
        // Last is fallback "Fără maistru"
        $this->assertEquals(0, end($rows)['id']);
    }

    public function test_matrix_places_event_in_correct_cell_and_sums_load(): void
    {
        $post = Post::create(['name' => 'Pod 1', 'color' => '#3B82F6', 'is_active' => true, 'hours_per_day' => 10]);
        $client = Client::create(['name' => 'C', 'phone' => '+37399000111', 'type' => 'individual', 'status' => 'active']);
        Appointment::create([
            'post_id' => $post->id, 'client_id' => $client->id,
            'date' => $this->monday, 'time_start' => '08:00', 'time_end' => '12:00',
            'title' => 'BMW frâne', 'status' => 'scheduled',
        ]);
        Appointment::create([
            'post_id' => $post->id, 'client_id' => $client->id,
            'date' => $this->monday, 'time_start' => '13:00', 'time_end' => '17:30',
            'title' => 'VW ulei', 'status' => 'scheduled',
        ]);

        $page = new CalendarBoard;
        $page->weekStart = $this->monday;
        $page->groupBy = 'post';
        $matrix = $page->getMatrix();

        $this->assertCount(2, $matrix[$post->id][$this->monday]['events']);
        // 4h + 4.5h = 8.5h
        $this->assertEqualsWithDelta(8.5, $matrix[$post->id][$this->monday]['load_hours'], 0.01);
        $this->assertEquals(10.0, $matrix[$post->id][$this->monday]['capacity']);
    }

    public function test_move_event_reassigns_post_and_date(): void
    {
        $post1 = Post::create(['name' => 'Pod 1', 'color' => '#3B82F6', 'is_active' => true]);
        $post2 = Post::create(['name' => 'Pod 2', 'color' => '#EF4444', 'is_active' => true]);
        $a = Appointment::create([
            'post_id' => $post1->id,
            'date' => $this->monday, 'time_start' => '09:00', 'time_end' => '10:00',
            'title' => 'Test', 'status' => 'scheduled',
        ]);

        Livewire::test(CalendarBoard::class)
            ->set('weekStart', $this->monday)
            ->set('groupBy', 'post')
            ->call('moveEvent', $a->id, $post2->id, Carbon::parse($this->monday)->addDays(2)->toDateString());

        $a->refresh();
        $this->assertEquals($post2->id, $a->post_id);
        $this->assertEquals(Carbon::parse($this->monday)->addDays(2)->toDateString(), $a->date->toDateString());
    }

    public function test_create_appt_inserts_appointment(): void
    {
        $post = Post::create(['name' => 'Pod 1', 'color' => '#3B82F6', 'is_active' => true]);

        Livewire::test(CalendarBoard::class)
            ->call('openNewForm', $post->id, $this->monday)
            ->set('newAppt.title', 'Schimb ulei')
            ->set('newAppt.time_start', '10:00')
            ->set('newAppt.time_end', '11:00')
            ->call('createAppt')
            ->assertSet('showNewForm', false);

        $appt = Appointment::where('title', 'Schimb ulei')->first();
        $this->assertNotNull($appt);
        $this->assertEquals($post->id, $appt->post_id);
        $this->assertEquals($this->monday, $appt->date->toDateString());
    }

    public function test_stats_compute_utilization_from_events(): void
    {
        $post = Post::create(['name' => 'Pod 1', 'color' => '#3B82F6', 'is_active' => true, 'hours_per_day' => 10]);
        Appointment::create([
            'post_id' => $post->id,
            'date' => $this->monday, 'time_start' => '08:00', 'time_end' => '16:00',
            'title' => 'X', 'status' => 'arrived',
        ]);

        $page = new CalendarBoard;
        $page->weekStart = $this->monday;
        $stats = $page->getStats();

        $this->assertEqualsWithDelta(8.0, $stats['scheduled_hours'], 0.01);
        $this->assertEquals(60.0, $stats['capacity_hours']);   // 10h × 6 days
        $this->assertEquals(13, $stats['utilization_pct']);    // 8/60 = 13%
        $this->assertEquals(1, $stats['confirmed_count']);
    }

    public function test_status_filter_narrows_events(): void
    {
        $post = Post::create(['name' => 'Pod 1', 'color' => '#3B82F6', 'is_active' => true]);
        Appointment::create(['post_id' => $post->id, 'date' => $this->monday, 'time_start' => '09:00', 'time_end' => '10:00', 'title' => 'A', 'status' => 'scheduled']);
        Appointment::create(['post_id' => $post->id, 'date' => $this->monday, 'time_start' => '10:00', 'time_end' => '11:00', 'title' => 'B', 'status' => 'arrived']);

        $page = new CalendarBoard;
        $page->weekStart = $this->monday;
        $page->statusFilter = 'confirmed';
        $matrix = $page->getMatrix();

        $events = $matrix[$post->id][$this->monday]['events'];
        $this->assertCount(1, $events);
        $this->assertEquals('B', $events[0]['title']);
    }
}
