<?php

declare(strict_types=1);

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

uses(RefreshDatabase::class);

beforeEach(function () {
    $this->seed();
});

test('unauthorized users cannot view or manage menus list', function () {
    $user = User::where('email', 'user@example.com')->first();
    
    $this->actingAs($user)
        ->get(route('menus.index'))
        ->assertStatus(403);
});

test('authorized users can view menus manager dashboard', function () {
    $admin = User::where('email', 'admin@example.com')->first();
    
    $this->actingAs($admin)
        ->get(route('menus.index'))
        ->assertOk();
});

test('authorized users can create a new menu item and trigger activity log', function () {
    $admin = User::where('email', 'admin@example.com')->first();

    $this->actingAs($admin)
        ->post(route('menus.store'), [
            'title' => 'Test Page',
            'href' => '/test-page',
            'group_name' => 'Main Menu',
            'icon' => 'HelpCircle',
            'roles' => ['User'],
            'permissions' => ['view dashboard'],
            'sort_order' => 10,
            'parent_id' => null,
        ])
        ->assertRedirect();

    $menu = Menu::where('href', '/test-page')->first();
    expect($menu)->not->toBeNull();
    expect($menu->title)->toBe('Test Page');
    expect($menu->roles)->toBe(['User']);
    expect($menu->permissions)->toBe(['view dashboard']);
    expect($menu->sort_order)->toBe(10);

    // Verify activity logged
    $this->assertDatabaseHas('activity_log', [
        'description' => 'Created menu item: Test Page (/test-page)',
        'causer_id' => $admin->id,
        'subject_id' => $menu->id,
    ]);
});

test('authorized users can update menu details', function () {
    $admin = User::where('email', 'admin@example.com')->first();
    $menu = Menu::create([
        'title' => 'Old Title',
        'href' => '/old-href',
        'group_name' => 'Main Menu',
        'icon' => 'HelpCircle',
        'sort_order' => 5,
    ]);

    $this->actingAs($admin)
        ->put(route('menus.update', $menu->id), [
            'title' => 'New Title',
            'href' => '/new-href',
            'group_name' => 'Administration',
            'icon' => 'Settings',
            'roles' => ['Admin'],
            'permissions' => [],
            'sort_order' => 7,
            'parent_id' => null,
        ])
        ->assertRedirect();

    $menu->refresh();
    expect($menu->title)->toBe('New Title');
    expect($menu->href)->toBe('/new-href');
    expect($menu->group_name)->toBe('Administration');
    expect($menu->icon)->toBe('Settings');
    expect($menu->roles)->toBe(['Admin']);
    expect($menu->sort_order)->toBe(7);

    // Verify activity logged
    $this->assertDatabaseHas('activity_log', [
        'description' => 'Updated menu item: New Title (/new-href)',
        'causer_id' => $admin->id,
        'subject_id' => $menu->id,
    ]);
});

test('a menu item cannot be its own parent', function () {
    $admin = User::where('email', 'admin@example.com')->first();
    $menu = Menu::create([
        'title' => 'Menu Item',
        'href' => '/href',
        'group_name' => 'Main Menu',
        'icon' => 'HelpCircle',
        'sort_order' => 5,
    ]);

    $this->actingAs($admin)
        ->put(route('menus.update', $menu->id), [
            'title' => 'Menu Item',
            'href' => '/href',
            'group_name' => 'Main Menu',
            'icon' => 'HelpCircle',
            'sort_order' => 5,
            'parent_id' => $menu->id, // self parent
        ])
        ->assertSessionHasErrors(['parent_id']);
});

test('authorized users can delete a menu item', function () {
    $admin = User::where('email', 'admin@example.com')->first();
    $menu = Menu::create([
        'title' => 'To Delete',
        'href' => '/to-delete',
        'group_name' => 'Main Menu',
        'icon' => 'HelpCircle',
        'sort_order' => 5,
    ]);

    $this->actingAs($admin)
        ->delete(route('menus.destroy', $menu->id))
        ->assertRedirect()
        ->assertSessionHas('success', 'Menu item deleted successfully.');

    expect(Menu::where('id', $menu->id)->exists())->toBeFalse();

    // Verify activity logged
    $this->assertDatabaseHas('activity_log', [
        'description' => 'Deleted menu item: To Delete (/to-delete)',
        'causer_id' => $admin->id,
    ]);
});

test('authorized users can rename a menu group', function () {
    $admin = User::where('email', 'admin@example.com')->first();
    
    $menu1 = Menu::create([
        'title' => 'Menu 1',
        'href' => '/menu-1',
        'group_name' => 'Old Group',
        'icon' => 'HelpCircle',
        'sort_order' => 1,
    ]);
    
    $menu2 = Menu::create([
        'title' => 'Menu 2',
        'href' => '/menu-2',
        'group_name' => 'Old Group',
        'icon' => 'HelpCircle',
        'sort_order' => 2,
    ]);

    $this->actingAs($admin)
        ->post(route('menus.groups.rename'), [
            'old_name' => 'Old Group',
            'new_name' => 'New Group',
        ])
        ->assertRedirect()
        ->assertSessionHas('success', 'Menu group renamed successfully.');

    expect(Menu::where('group_name', 'Old Group')->count())->toBe(0);
    expect(Menu::where('group_name', 'New Group')->count())->toBe(2);

    // Verify activity logged
    $this->assertDatabaseHas('activity_log', [
        'description' => 'Renamed menu group: Old Group to New Group',
        'causer_id' => $admin->id,
    ]);
});

test('authorized users can delete a menu group and all its items', function () {
    $admin = User::where('email', 'admin@example.com')->first();

    $menu1 = Menu::create([
        'title' => 'Menu 1',
        'href' => '/menu-1',
        'group_name' => 'Delete Group',
        'icon' => 'HelpCircle',
        'sort_order' => 1,
    ]);
    
    $menu2 = Menu::create([
        'title' => 'Menu 2',
        'href' => '/menu-2',
        'group_name' => 'Delete Group',
        'icon' => 'HelpCircle',
        'sort_order' => 2,
    ]);

    $this->actingAs($admin)
        ->post(route('menus.groups.delete'), [
            'group_name' => 'Delete Group',
        ])
        ->assertRedirect()
        ->assertSessionHas('success', 'Menu group and all its items deleted successfully.');

    expect(Menu::where('group_name', 'Delete Group')->exists())->toBeFalse();

    // Verify activity logged
    $this->assertDatabaseHas('activity_log', [
        'description' => 'Deleted menu group and all its items: Delete Group',
        'causer_id' => $admin->id,
    ]);
});

test('unauthorized users cannot rename or delete menu groups', function () {
    $user = User::where('email', 'user@example.com')->first();

    $this->actingAs($user)
        ->post(route('menus.groups.rename'), [
            'old_name' => 'Some Group',
            'new_name' => 'New Name',
        ])
        ->assertStatus(403);

    $this->actingAs($user)
        ->post(route('menus.groups.delete'), [
            'group_name' => 'Some Group',
        ])
        ->assertStatus(403);
});
