<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\Holiday;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;

class HolidaysControllerTest extends TestCase
{
    use RefreshDatabase;

    protected $user;

    protected function setUp(): void
    {
        parent::setUp();
        
        $this->user = User::create([
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => bcrypt('password'),
        ]);
    }

    /** @test */
    public function it_can_display_holidays_index_page()
    {
        $this->actingAs($this->user);

        $response = $this->get(route('holidays.index'));

        $response->assertStatus(200);
        $response->assertViewIs('m-holidays.index');
        $response->assertViewHas('variables');
    }

    /** @test */
    public function it_can_get_holidays_data_via_ajax()
    {
        $this->actingAs($this->user);

        // Create test holidays
        Holiday::create([
            'name' => 'New Year',
            'date' => Carbon::now()->format('Y') . '-01-01',
            'type' => 'National',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('holidays.index'), [
            'draw' => 1,
            'start' => 0,
            'length' => 10,
            'search' => ['value' => ''],
            'order' => [['column' => 2, 'dir' => 'asc']]
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'draw',
            'recordsTotal',
            'recordsFiltered',
            'data'
        ]);
    }

    /** @test */
    public function it_can_search_holidays_via_ajax()
    {
        $this->actingAs($this->user);

        Holiday::create([
            'name' => 'Christmas',
            'date' => Carbon::now()->format('Y') . '-12-25',
            'type' => 'Religious',
            'is_active' => true,
            'delete_flag' => false
        ]);

        Holiday::create([
            'name' => 'New Year',
            'date' => Carbon::now()->format('Y') . '-01-01',
            'type' => 'National',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('holidays.index'), [
            'draw' => 1,
            'start' => 0,
            'length' => 10,
            'search' => ['value' => 'Christmas'],
            'order' => [['column' => 2, 'dir' => 'asc']]
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

        $response->assertStatus(200);
        $data = $response->json('data');
        $this->assertCount(1, $data);
        $this->assertStringContainsString('Christmas', $data[0][1]);
    }

    /** @test */
    public function it_can_filter_holidays_by_year()
    {
        $this->actingAs($this->user);

        Holiday::create([
            'name' => 'Holiday 2024',
            'date' => '2024-01-01',
            'type' => 'National',
            'is_active' => true,
            'delete_flag' => false
        ]);

        Holiday::create([
            'name' => 'Holiday 2025',
            'date' => '2025-01-01',
            'type' => 'National',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('holidays.index'), [
            'draw' => 1,
            'start' => 0,
            'length' => 10,
            'year' => 2024,
            'search' => ['value' => ''],
            'order' => [['column' => 2, 'dir' => 'asc']]
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

        $response->assertStatus(200);
        $data = $response->json('data');
        $this->assertCount(1, $data);
        $this->assertStringContainsString('Holiday 2024', $data[0][1]);
    }

    /** @test */
    public function it_can_display_create_holiday_form()
    {
        $this->actingAs($this->user);

        $response = $this->get(route('holidays.create'));

        $response->assertStatus(200);
        $response->assertViewIs('m-holidays.form');
        $response->assertViewHas('data');
        $response->assertViewHas('variables');
    }

    /** @test */
    public function it_can_create_new_holiday()
    {
        $this->actingAs($this->user);

        $holidayData = [
            'name' => 'Test Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'description' => 'Test holiday description',
            'is_recurring' => true,
            'recurring_type' => 'Yearly',
            'is_active' => true
        ];

        $response = $this->json('POST', route('holidays.store'), $holidayData);

        $response->assertStatus(200);
        $response->assertJson(['success']);

        $this->assertDatabaseHas('m_holidays', [
            'name' => 'Test Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_recurring' => true,
            'recurring_type' => 'Yearly',
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

    /** @test */
    public function it_validates_required_fields_when_creating_holiday()
    {
        $this->actingAs($this->user);

        $response = $this->json('POST', route('holidays.store'), []);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['name', 'date', 'type', 'recurring_type']);
    }

    /** @test */
    public function it_validates_date_format()
    {
        $this->actingAs($this->user);

        $response = $this->json('POST', route('holidays.store'), [
            'name' => 'Test Holiday',
            'date' => 'invalid-date',
            'type' => 'Company',
            'recurring_type' => 'None'
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['date']);
    }

    /** @test */
    public function it_validates_type_enum()
    {
        $this->actingAs($this->user);

        $response = $this->json('POST', route('holidays.store'), [
            'name' => 'Test Holiday',
            'date' => '2024-06-15',
            'type' => 'InvalidType',
            'recurring_type' => 'None'
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['type']);
    }

    /** @test */
    public function it_can_display_edit_holiday_form()
    {
        $this->actingAs($this->user);

        $holiday = Holiday::create([
            'name' => 'Test Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('holidays.edit', $holiday));

        $response->assertStatus(200);
        $response->assertViewIs('m-holidays.form');
        $response->assertViewHas('data', $holiday);
    }

    /** @test */
    public function it_can_update_existing_holiday()
    {
        $this->actingAs($this->user);

        $holiday = Holiday::create([
            'name' => 'Original Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $updateData = [
            'name' => 'Updated Holiday',
            'date' => '2024-06-16',
            'type' => 'National',
            'description' => 'Updated description',
            'is_recurring' => false,
            'recurring_type' => 'None',
            'is_active' => false
        ];

        $response = $this->json('POST', route('holidays.store', $holiday->id), $updateData);

        $response->assertStatus(200);
        $response->assertJson(['success']);

        $holiday->refresh();
        $this->assertEquals('Updated Holiday', $holiday->name);
        $this->assertEquals('2024-06-16', $holiday->date->format('Y-m-d'));
        $this->assertEquals('National', $holiday->type);
        $this->assertFalse($holiday->is_active);
    }

    /** @test */
    public function it_can_display_holiday_details()
    {
        $this->actingAs($this->user);

        $holiday = Holiday::create([
            'name' => 'Test Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'description' => 'Test description',
            'is_active' => true,
            'delete_flag' => false,
            'created_by' => $this->user->id
        ]);

        $response = $this->get(route('holidays.show', $holiday));

        $response->assertStatus(200);
        $response->assertViewIs('m-holidays.show');
        $response->assertViewHas('data', $holiday);
    }

    /** @test */
    public function it_can_delete_holiday()
    {
        $this->actingAs($this->user);

        $holiday = Holiday::create([
            'name' => 'Test Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->delete(route('holidays.destroy', $holiday));

        $response->assertRedirect(route('holidays.index'));
        $response->assertSessionHas('success');

        $holiday->refresh();
        $this->assertTrue($holiday->delete_flag);
    }

    /** @test */
    public function it_can_check_if_date_is_holiday()
    {
        $this->actingAs($this->user);

        Holiday::create([
            'name' => 'Test Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('holidays.check'), [
            'date' => '2024-06-15'
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'date' => '2024-06-15',
            'is_holiday' => true,
            'holiday' => [
                'name' => 'Test Holiday',
                'type' => 'Company'
            ]
        ]);
    }

    /** @test */
    public function it_returns_false_for_non_holiday_date()
    {
        $this->actingAs($this->user);

        $response = $this->json('GET', route('holidays.check'), [
            'date' => '2024-06-16'
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'date' => '2024-06-16',
            'is_holiday' => false,
            'holiday' => null
        ]);
    }

    /** @test */
    public function it_validates_date_parameter_for_check_holiday()
    {
        $this->actingAs($this->user);

        $response = $this->json('GET', route('holidays.check'));

        $response->assertStatus(400);
        $response->assertJson(['error' => 'Date parameter required']);
    }

    /** @test */
    public function it_can_get_holidays_in_date_range()
    {
        $this->actingAs($this->user);

        Holiday::create([
            'name' => 'Holiday 1',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_active' => true,
            'delete_flag' => false
        ]);

        Holiday::create([
            'name' => 'Holiday 2',
            'date' => '2024-06-20',
            'type' => 'National',
            'is_active' => true,
            'delete_flag' => false
        ]);

        Holiday::create([
            'name' => 'Holiday 3',
            'date' => '2024-07-01',
            'type' => 'Religious',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('holidays.range'), [
            'start_date' => '2024-06-01',
            'end_date' => '2024-06-30'
        ]);

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'start_date',
            'end_date',
            'holidays' => [
                '*' => ['name', 'date', 'formatted_date', 'type', 'description']
            ]
        ]);

        $holidays = $response->json('holidays');
        $this->assertCount(2, $holidays);
    }

    /** @test */
    public function it_validates_date_range_parameters()
    {
        $this->actingAs($this->user);

        $response = $this->json('GET', route('holidays.range'), [
            'start_date' => '2024-06-01'
            // Missing end_date
        ]);

        $response->assertStatus(400);
        $response->assertJson(['error' => 'start_date and end_date parameters required']);
    }

    /** @test */
    public function it_can_generate_recurring_holidays()
    {
        $this->actingAs($this->user);

        // Create recurring holiday
        Holiday::create([
            'name' => 'Annual Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_recurring' => true,
            'recurring_type' => 'Yearly',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('holidays.generate'), [
            'year' => 2025
        ]);

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'target_year',
            'generated_count',
            'holidays'
        ]);

        $this->assertDatabaseHas('m_holidays', [
            'name' => 'Annual Holiday',
            'date' => '2025-06-15',
            'is_recurring' => true
        ]);
    }

    /** @test */
    public function it_does_not_duplicate_existing_holidays_when_generating()
    {
        $this->actingAs($this->user);

        // Create recurring holiday
        Holiday::create([
            'name' => 'Annual Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_recurring' => true,
            'recurring_type' => 'Yearly',
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Create holiday for target year already
        Holiday::create([
            'name' => 'Existing Holiday',
            'date' => '2025-06-15',
            'type' => 'Company',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('holidays.generate'), [
            'year' => 2025
        ]);

        $response->assertStatus(200);
        $generatedCount = $response->json('generated_count');
        $this->assertEquals(0, $generatedCount);
    }

    /** @test */
    public function it_uses_current_year_plus_one_as_default_for_generation()
    {
        $this->actingAs($this->user);

        Holiday::create([
            'name' => 'Annual Holiday',
            'date' => '2024-06-15',
            'type' => 'Company',
            'is_recurring' => true,
            'recurring_type' => 'Yearly',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('holidays.generate'));

        $response->assertStatus(200);
        $targetYear = $response->json('target_year');
        $this->assertEquals(Carbon::now()->addYear()->year, $targetYear);
    }
}