<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\Period;
use App\Models\User;
use App\Models\RawMaterial;
use Illuminate\Foundation\Testing\RefreshDatabase;

class PeriodsControllerTest 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_periods_index_page()
    {
        $this->actingAs($this->user);

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

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

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

        Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'description' => 'First quarter',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('periods.index'), [
            'draw' => 1,
            'start' => 0,
            'length' => 10
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

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

        $data = $response->json('data');
        $this->assertCount(1, $data);
        $this->assertStringContainsString('Q1', $data[0][1]);
        $this->assertStringContainsString('Quarter 1', $data[0][2]);
    }

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

        Period::create([
            'code' => 'Q1',
            'name' => 'Active Quarter',
            'is_active' => true,
            'delete_flag' => false
        ]);

        Period::create([
            'code' => 'Q2',
            'name' => 'Inactive Quarter',
            'is_active' => false,
            'delete_flag' => false
        ]);

        Period::create([
            'code' => 'Q3',
            'name' => 'Deleted Quarter',
            'is_active' => true,
            'delete_flag' => true
        ]);

        $response = $this->json('GET', route('periods.index'), [
            'draw' => 1
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

        $response->assertStatus(200);
        $data = $response->json('data');
        $this->assertCount(1, $data); // Only active and not deleted
        $this->assertStringContainsString('Active Quarter', $data[0][2]);
    }

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

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

        $response->assertStatus(200);
        $response->assertViewIs('m-periods.form');
        $response->assertViewHas('data');
        $response->assertViewHas('variables');
        
        $data = $response->viewData('data');
        $this->assertEquals(0, $data->id);
        $this->assertTrue($data->is_active);
    }

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

        $periodData = [
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'description' => 'First quarter of the year',
            'is_active' => true
        ];

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

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

        $this->assertDatabaseHas('m_periods', [
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'description' => 'First quarter of the year',
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

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

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

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

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

        Period::create([
            'code' => 'Q1',
            'name' => 'Existing Quarter',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('periods.store'), [
            'code' => 'Q1',
            'name' => 'New Quarter'
        ]);

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

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

        Period::create([
            'code' => 'Q1',
            'name' => 'Deleted Quarter',
            'is_active' => true,
            'delete_flag' => true // Deleted
        ]);

        $response = $this->json('POST', route('periods.store'), [
            'code' => 'Q1',
            'name' => 'New Quarter',
            'is_active' => true
        ]);

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

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

        $response = $this->json('POST', route('periods.store'), [
            'code' => str_repeat('A', 21), // Too long
            'name' => str_repeat('B', 101), // Too long
            'description' => str_repeat('C', 256) // Too long
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['code', 'name', 'description']);
    }

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'description' => 'First quarter',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('periods.edit', $period));

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

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Deleted Quarter',
            'is_active' => true,
            'delete_flag' => true
        ]);

        $response = $this->get(route('periods.edit', $period));

        $response->assertRedirect(route('periods.index'));
        $response->assertSessionHas('error', 'Period not found.');
    }

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Original Quarter',
            'description' => 'Original description',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $updateData = [
            'code' => 'Q1-UPDATED',
            'name' => 'Updated Quarter',
            'description' => 'Updated description',
            'is_active' => false
        ];

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

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

        $period->refresh();
        $this->assertEquals('Q1-UPDATED', $period->code);
        $this->assertEquals('Updated Quarter', $period->name);
        $this->assertEquals('Updated description', $period->description);
        $this->assertFalse($period->is_active);
    }

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

        $period1 = Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $period2 = Period::create([
            'code' => 'Q2',
            'name' => 'Quarter 2',
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Try to update period2 with period1's code
        $response = $this->json('POST', route('periods.store', $period2->id), [
            'code' => 'Q1',
            'name' => 'Updated Quarter 2'
        ]);

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

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('periods.store', $period->id), [
            'code' => 'Q1', // Same code
            'name' => 'Updated Quarter 1'
        ]);

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

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'description' => 'First quarter',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('periods.show', $period));

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

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Deleted Quarter',
            'is_active' => true,
            'delete_flag' => true
        ]);

        $response = $this->get(route('periods.show', $period));

        $response->assertRedirect(route('periods.index'));
        $response->assertSessionHas('error', 'Period not found.');
    }

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->delete(route('periods.destroy', $period));

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

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

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Create raw material that uses this period
        $rawMaterial = RawMaterial::create([
            'code' => 'RM001',
            'name' => 'Test Raw Material',
            'unit' => 'kg',
            'period_id' => $period->id,
            'delete_flag' => false
        ]);

        $response = $this->json('DELETE', route('periods.destroy', $period));

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

        $period->refresh();
        $this->assertFalse($period->delete_flag); // Should not be deleted
    }

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

        $period = Period::create([
            'code' => 'Q1',
            'name' => 'Quarter 1',
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Create deleted raw material that uses this period
        RawMaterial::create([
            'code' => 'RM001',
            'name' => 'Deleted Raw Material',
            'unit' => 'kg',
            'period_id' => $period->id,
            'delete_flag' => true // Deleted
        ]);

        $response = $this->delete(route('periods.destroy', $period));

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

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

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

        // Test with checkbox checked
        $response1 = $this->json('POST', route('periods.store'), [
            'code' => 'Q1',
            'name' => 'Active Quarter',
            'is_active' => 'on' // Checkbox value
        ]);

        $response1->assertStatus(200);
        $this->assertDatabaseHas('m_periods', [
            'code' => 'Q1',
            'is_active' => true
        ]);

        // Test with checkbox unchecked
        $response2 = $this->json('POST', route('periods.store'), [
            'code' => 'Q2',
            'name' => 'Inactive Quarter'
            // is_active not present (unchecked)
        ]);

        $response2->assertStatus(200);
        $this->assertDatabaseHas('m_periods', [
            'code' => 'Q2',
            'is_active' => false
        ]);
    }
}