<?php

use App\Models\Group;
use App\Models\Menu;
use App\Models\MenuType;
use App\Services\NavigationService;

use function Pest\Laravel\actingAs;

beforeEach(function () {
    Group::firstOrCreate(['name' => Group::ADMIN]);
    Group::firstOrCreate(['name' => Group::MEMBERS]);

    // Seed menu minimal untuk test (bukan seeder penuh).
    $side = MenuType::firstOrCreate(['type' => 'Side menu']);
    $adminGroup = Group::where('name', Group::ADMIN)->first();
    $memberGroup = Group::where('name', Group::MEMBERS)->first();

    $dashboard = Menu::create(['label' => 'Dashboard', 'route' => 'dashboard', 'icon' => 'layout-grid', 'section' => 'Utama', 'menu_type_id' => $side->id, 'sort_order' => 0, 'status' => true]);
    $dashboard->groups()->sync([$adminGroup->id, $memberGroup->id]);

    $users = Menu::create(['label' => 'Pengguna', 'route' => 'users.index', 'icon' => 'users', 'section' => 'Sistem', 'menu_type_id' => $side->id, 'sort_order' => 1, 'status' => true]);
    $users->groups()->sync([$adminGroup->id]); // admin only
});

test('admin sees all assigned menus including admin-only sections', function () {
    $admin = makeAdmin();

    $nav = app(NavigationService::class)->forUser($admin);
    $labels = collect($nav)->flatMap(fn ($s) => $s['items'])->pluck('label');

    expect($labels)->toContain('Dashboard')
        ->and($labels)->toContain('Pengguna');
});

test('member does not see admin-only menus', function () {
    $member = makeMember();

    $nav = app(NavigationService::class)->forUser($member);
    $labels = collect($nav)->flatMap(fn ($s) => $s['items'])->pluck('label');

    expect($labels)->toContain('Dashboard')
        ->and($labels)->not->toContain('Pengguna');
});

test('menus are grouped by section', function () {
    $admin = makeAdmin();

    $nav = app(NavigationService::class)->forUser($admin);
    $sections = collect($nav)->pluck('label');

    expect($sections)->toContain('Utama')
        ->and($sections)->toContain('Sistem');
});

test('admin can create a menu with group access', function () {
    $admin = makeAdmin();
    $side = MenuType::where('type', 'Side menu')->first();
    $memberGroup = Group::where('name', Group::MEMBERS)->first();

    $response = actingAs($admin)->post(route('menus.store'), [
        'label' => 'Laporan',
        'route' => 'dashboard',
        'icon' => 'file-text',
        'section' => 'Laporan',
        'menu_type_id' => $side->id,
        'sort_order' => 5,
        'status' => true,
        'groups' => [$memberGroup->id],
    ]);

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

    $menu = Menu::where('label', 'Laporan')->first();
    expect($menu)->not->toBeNull()
        ->and($menu->groups->pluck('id'))->toContain($memberGroup->id);
});

test('admin can update menu and sync groups', function () {
    $admin = makeAdmin();
    $memberGroup = Group::where('name', Group::MEMBERS)->first();
    $adminGroup = Group::where('name', Group::ADMIN)->first();

    $menu = Menu::where('label', 'Pengguna')->first();

    actingAs($admin)->put(route('menus.update', $menu), [
        'label' => 'Manajemen Pengguna',
        'route' => 'users.index',
        'icon' => 'users',
        'section' => 'Sistem',
        'menu_type_id' => $menu->menu_type_id,
        'sort_order' => 1,
        'status' => true,
        'groups' => [$adminGroup->id, $memberGroup->id], // buka akses ke member
    ])->assertRedirect(route('menus.index'));

    $menu->refresh();
    expect($menu->label)->toBe('Manajemen Pengguna')
        ->and($menu->groups->contains($memberGroup->id))->toBeTrue();
});

test('member cannot access menu management', function () {
    $member = makeMember();

    actingAs($member)->get(route('menus.index'))->assertRedirect(route('dashboard'));
    actingAs($member)->get(route('menus.create'))->assertRedirect(route('dashboard'));
});

test('menus without a resolvable route or link are hidden', function () {
    $admin = makeAdmin();
    $side = MenuType::where('type', 'Side menu')->first();
    $adminGroup = Group::where('name', Group::ADMIN)->first();

    // Menu dengan route yang tidak ada & tanpa link → harus tersembunyi.
    Menu::create([
        'label' => 'Hantu', 'route' => 'tidak.ada', 'link' => null,
        'section' => 'Hantu', 'menu_type_id' => $side->id, 'sort_order' => 99, 'status' => true,
    ])->groups()->sync([$adminGroup->id]);

    $nav = app(NavigationService::class)->forUser($admin);
    $labels = collect($nav)->flatMap(fn ($s) => $s['items'])->pluck('label');

    expect($labels)->not->toContain('Hantu');
});
