<?php

namespace Tests\Feature;

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

class FstrsControllerTest extends TestCase
{
    use RefreshDatabase;

    protected $user;
    protected $rawMaterial;

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

        $this->rawMaterial = RawMaterial::create([
            'code' => 'RM001',
            'name' => 'Test Raw Material',
            'unit_pakai' => 'KG',
            'unit_utuh' => 'SACK',
            'unit_kirim' => 'SACK',
            'konversi_satuan_utuh' => 'SACK',
            'konversi_satuan_pakai' => 'KG',
            'konversi_satuan_kirim' => 'SACK',
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

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

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

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

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

        Fstr::create([
            'name' => 'Kah Mie Ayam',
            'description' => 'Processed chicken noodle dish',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

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

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

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

        Fstr::create([
            'name' => 'Kah Mie Ayam',
            'description' => 'Processed chicken noodle dish',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        Fstr::create([
            'name' => 'Kah Nasi Goreng',
            'description' => 'Processed fried rice',
            'total_cost' => 45000,
            'is_active' => true,
            'delete_flag' => false
        ]);

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

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

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

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

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

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

        $fstrData = [
            'name' => 'Kah Mie Ayam Special',
            'description' => 'Special processed chicken noodle dish',
            'recipe_data' => [
                'ingredients' => [
                    ['raw_material_id' => $this->rawMaterial->id, 'quantity' => 2, 'unit' => 'KG']
                ]
            ],
            'is_active' => true,
            'details' => [
                [
                    'raw_material_id' => $this->rawMaterial->id,
                    'quantity' => 2,
                    'unit' => 'KG',
                    'unit_cost' => 15000,
                    'total_cost' => 30000
                ]
            ]
        ];

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

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

        $this->assertDatabaseHas('m_fstrs', [
            'name' => 'Kah Mie Ayam Special',
            'description' => 'Special processed chicken noodle dish',
            'total_cost' => 30000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $fstr = Fstr::where('name', 'Kah Mie Ayam Special')->first();
        $this->assertDatabaseHas('m_fstr_details', [
            'fstr_id' => $fstr->id,
            'raw_material_id' => $this->rawMaterial->id,
            'quantity' => 2,
            'unit' => 'KG',
            'unit_cost' => 15000,
            'total_cost' => 30000
        ]);
    }

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

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

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

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

        $response = $this->json('POST', route('fstrs.store'), [
            'name' => 'Test FSTR',
            'details' => [
                [
                    'raw_material_id' => $this->rawMaterial->id,
                    'quantity' => 'invalid',
                    'unit' => 'KG'
                ]
            ]
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['details.0.quantity']);
    }

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

        $fstr = Fstr::create([
            'name' => 'Test FSTR',
            'description' => 'Test description',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('fstrs.edit', $fstr));

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

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

        $fstr = Fstr::create([
            'name' => 'Original FSTR',
            'description' => 'Original description',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $updateData = [
            'name' => 'Updated FSTR',
            'description' => 'Updated description',
            'recipe_data' => [
                'ingredients' => [
                    ['raw_material_id' => $this->rawMaterial->id, 'quantity' => 3, 'unit' => 'KG']
                ]
            ],
            'is_active' => false,
            'details' => [
                [
                    'raw_material_id' => $this->rawMaterial->id,
                    'quantity' => 3,
                    'unit' => 'KG',
                    'unit_cost' => 20000,
                    'total_cost' => 60000
                ]
            ]
        ];

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

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

        $fstr->refresh();
        $this->assertEquals('Updated FSTR', $fstr->name);
        $this->assertEquals('Updated description', $fstr->description);
        $this->assertEquals(60000, $fstr->total_cost);
        $this->assertFalse($fstr->is_active);
    }

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

        $fstr = Fstr::create([
            'name' => 'Test FSTR',
            'description' => 'Test description',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false,
            'created_by' => $this->user->id
        ]);

        FstrDetail::create([
            'fstr_id' => $fstr->id,
            'raw_material_id' => $this->rawMaterial->id,
            'quantity' => 2,
            'unit' => 'KG',
            'unit_cost' => 25000,
            'total_cost' => 50000,
            'delete_flag' => false
        ]);

        $response = $this->get(route('fstrs.show', $fstr));

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

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

        $fstr = Fstr::create([
            'name' => 'Test FSTR',
            'description' => 'Test description',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->delete(route('fstrs.destroy', $fstr));

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

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

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

        $fstr = Fstr::create([
            'name' => 'Test FSTR',
            'description' => 'Test description',
            'total_cost' => 0,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('fstrs.calculate_cost'), [
            'details' => [
                [
                    'raw_material_id' => $this->rawMaterial->id,
                    'quantity' => 2,
                    'unit' => 'KG',
                    'unit_cost' => 15000,
                    'total_cost' => 30000
                ],
                [
                    'raw_material_id' => $this->rawMaterial->id,
                    'quantity' => 1,
                    'unit' => 'KG',
                    'unit_cost' => 20000,
                    'total_cost' => 20000
                ]
            ]
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'total_cost' => 50000,
            'formatted_total_cost' => 'Rp 50.000'
        ]);
    }

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

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

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

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

        Fstr::create([
            'name' => 'Active FSTR',
            'description' => 'Active FSTR description',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        Fstr::create([
            'name' => 'Inactive FSTR',
            'description' => 'Inactive FSTR description',
            'total_cost' => 40000,
            'is_active' => false,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('fstrs.active'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'fstrs' => [
                '*' => ['id', 'code', 'name', 'description', 'total_cost', 'formatted_total_cost']
            ]
        ]);

        $fstrs = $response->json('fstrs');
        $this->assertCount(1, $fstrs);
        $this->assertEquals('Active FSTR', $fstrs[0]['name']);
    }

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

        $recipeData = [
            'ingredients' => [
                ['raw_material_id' => $this->rawMaterial->id, 'quantity' => 2, 'unit' => 'KG']
            ],
            'instructions' => [
                'Step 1: Prepare ingredients',
                'Step 2: Cook for 30 minutes'
            ]
        ];

        $fstr = Fstr::create([
            'name' => 'Test FSTR',
            'description' => 'Test description',
            'recipe_data' => $recipeData,
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        FstrDetail::create([
            'fstr_id' => $fstr->id,
            'raw_material_id' => $this->rawMaterial->id,
            'quantity' => 2,
            'unit' => 'KG',
            'unit_cost' => 25000,
            'total_cost' => 50000,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('fstrs.recipe', $fstr));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'fstr' => ['id', 'code', 'name', 'description', 'recipe_data', 'total_cost'],
            'details' => [
                '*' => ['id', 'raw_material_id', 'raw_material', 'quantity', 'unit', 'unit_cost', 'total_cost']
            ]
        ]);

        $responseData = $response->json();
        $this->assertEquals($recipeData, $responseData['fstr']['recipe_data']);
        $this->assertCount(1, $responseData['details']);
    }

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

        $fstr = Fstr::create([
            'name' => 'Test FSTR',
            'description' => 'Test description',
            'total_cost' => 50000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Create initial detail
        FstrDetail::create([
            'fstr_id' => $fstr->id,
            'raw_material_id' => $this->rawMaterial->id,
            'quantity' => 2,
            'unit' => 'KG',
            'unit_cost' => 25000,
            'total_cost' => 50000,
            'delete_flag' => false
        ]);

        // Update with new details
        $updateData = [
            'name' => 'Updated FSTR',
            'description' => 'Updated description',
            'is_active' => true,
            'details' => [
                [
                    'raw_material_id' => $this->rawMaterial->id,
                    'quantity' => 3,
                    'unit' => 'KG',
                    'unit_cost' => 20000,
                    'total_cost' => 60000
                ]
            ]
        ];

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

        $response->assertStatus(200);

        // Check that old details are marked as deleted
        $this->assertDatabaseHas('m_fstr_details', [
            'fstr_id' => $fstr->id,
            'quantity' => 2,
            'delete_flag' => true
        ]);

        // Check that new details are created
        $this->assertDatabaseHas('m_fstr_details', [
            'fstr_id' => $fstr->id,
            'quantity' => 3,
            'delete_flag' => false
        ]);
    }
}