<?php

namespace Tests\Feature;

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

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

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

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

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

        Menu::create([
            'name' => 'Bakmi Ayam',
            'menu_group' => 'Noodles',
            'plu_code' => 'PLU001',
            'category' => 'Main Course',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('menus.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_menus_via_ajax()
    {
        $this->actingAs($this->user);

        Menu::create([
            'name' => 'Bakmi Ayam',
            'menu_group' => 'Noodles',
            'plu_code' => 'PLU001',
            'category' => 'Main Course',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        Menu::create([
            'name' => 'Nasi Goreng',
            'menu_group' => 'Rice',
            'plu_code' => 'PLU002',
            'category' => 'Main Course',
            'price' => 30000,
            'is_active' => true,
            'delete_flag' => false
        ]);

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

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

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

        Menu::create([
            'name' => 'Bakmi Ayam',
            'menu_group' => 'Noodles',
            'plu_code' => 'PLU001',
            'category' => 'Main Course',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        Menu::create([
            'name' => 'Nasi Goreng',
            'menu_group' => 'Rice',
            'plu_code' => 'PLU002',
            'category' => 'Main Course',
            'price' => 30000,
            'is_active' => true,
            'delete_flag' => false
        ]);

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

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

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

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

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

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

        $menuData = [
            'name' => 'Bakmi Ayam Special',
            'menu_group' => 'Noodles',
            'plu_code' => 'PLU001',
            'category' => 'Main Course',
            'price' => 35000,
            'description' => 'Special chicken noodles with extra toppings',
            'is_active' => true
        ];

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

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

        $this->assertDatabaseHas('m_menus', [
            'name' => 'Bakmi Ayam Special',
            'menu_group' => 'Noodles',
            'plu_code' => 'PLU001',
            'category' => 'Main Course',
            'price' => 35000,
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

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

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

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['name', 'menu_group', 'plu_code', 'category', 'price']);
    }

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

        $response = $this->json('POST', route('menus.store'), [
            'name' => 'Test Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 'invalid'
        ]);

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

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

        $response = $this->json('POST', route('menus.store'), [
            'name' => 'Test Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => -1000
        ]);

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

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

        Menu::create([
            'name' => 'Existing Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('menus.store'), [
            'name' => 'New Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 30000
        ]);

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

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

        $menu = Menu::create([
            'name' => 'Test Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('menus.edit', $menu));

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

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

        $menu = Menu::create([
            'name' => 'Original Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $updateData = [
            'name' => 'Updated Menu',
            'menu_group' => 'Updated Group',
            'plu_code' => 'PLU001',
            'category' => 'Updated Category',
            'price' => 35000,
            'description' => 'Updated description',
            'is_active' => false
        ];

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

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

        $menu->refresh();
        $this->assertEquals('Updated Menu', $menu->name);
        $this->assertEquals('Updated Group', $menu->menu_group);
        $this->assertEquals(35000, $menu->price);
        $this->assertFalse($menu->is_active);
    }

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

        $menu = Menu::create([
            'name' => 'Test Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 25000,
            'description' => 'Test description',
            'is_active' => true,
            'delete_flag' => false,
            'created_by' => $this->user->id
        ]);

        $response = $this->get(route('menus.show', $menu));

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

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

        $menu = Menu::create([
            'name' => 'Test Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->delete(route('menus.destroy', $menu));

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

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

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

        Menu::create([
            'name' => 'Bakmi Ayam',
            'menu_group' => 'Noodles',
            'plu_code' => 'PLU001',
            'category' => 'Main Course',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        Menu::create([
            'name' => 'Mie Goreng',
            'menu_group' => 'Noodles',
            'plu_code' => 'PLU002',
            'category' => 'Main Course',
            'price' => 28000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        Menu::create([
            'name' => 'Nasi Goreng',
            'menu_group' => 'Rice',
            'plu_code' => 'PLU003',
            'category' => 'Main Course',
            'price' => 30000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('menus.by_group'), [
            'menu_group' => 'Noodles'
        ]);

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'menu_group',
            'menus' => [
                '*' => ['id', 'code', 'name', 'plu_code', 'category', 'price', 'formatted_price']
            ]
        ]);

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

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

        $response = $this->json('GET', route('menus.by_group'));

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

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

        Menu::create([
            'name' => 'Active Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU001',
            'category' => 'Test',
            'price' => 25000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        Menu::create([
            'name' => 'Inactive Menu',
            'menu_group' => 'Test',
            'plu_code' => 'PLU002',
            'category' => 'Test',
            'price' => 30000,
            'is_active' => false,
            'delete_flag' => false
        ]);

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

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'menus' => [
                '*' => ['id', 'code', 'name', 'plu_code', 'category', 'price', 'formatted_price']
            ]
        ]);

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