<?php

declare(strict_types=1);

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Maestro\Core\Database\Seeders\ModuleAndNavigationSeeder;
use Maestro\Core\Database\Seeders\UserSeeder;
use Maestro\Core\Models\MaestroModule;
use Maestro\Core\Models\NavigationNode;
use Maestro\Core\Support\PermissionGuardName;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;
use Tests\Fixtures\AuthTestUser;
use Tests\TestCase;

class NavigationApiTest extends TestCase
{
    use RefreshDatabase;

    /**
     * @return array<int, class-string>
     */
    private function seedDefaults(): array
    {
        return [UserSeeder::class, ModuleAndNavigationSeeder::class];
    }

    public function test_navigation_returns_filtered_tree_for_authenticated_user(): void
    {
        $this->seed($this->seedDefaults());

        MaestroModule::query()
            ->whereIn('slug', ['customers', 'offers', 'hours'])
            ->update(['is_enabled' => true]);

        $user = AuthTestUser::query()->where('email', 'demo@example.com')->first();
        self::assertNotNull($user);

        $response = $this->actingAs($user, 'web')->getJson('/api/navigation');

        $response->assertOk();
        $response->assertJsonCount(1);
        $payload = $response->json();
        self::assertSame('root', $payload[0]['key']);
        self::assertNotEmpty($payload[0]['items']);

        $keys = array_column($payload[0]['items'], 'key');
        self::assertContains('dashboard', $keys);
        self::assertContains('customers', $keys);
        self::assertContains('offers', $keys);
        self::assertContains('hours-week', $keys);
        self::assertContains('settings', $keys);
        self::assertContains('superadmin', $keys);

        $superadmin = collect($payload[0]['items'])->firstWhere('key', 'superadmin');
        self::assertIsArray($superadmin);
        self::assertArrayHasKey('items', $superadmin);
        self::assertCount(7, $superadmin['items']);
        $childKeys = array_column($superadmin['items'], 'key');
        self::assertContains('superadmin-installation-health', $childKeys);
        self::assertContains('superadmin-modules', $childKeys);
        self::assertContains('superadmin-datatable-settings', $childKeys);
        self::assertContains('superadmin-public-home', $childKeys);
        self::assertContains('superadmin-branding', $childKeys);
    }

    public function test_navigation_installs_default_tree_when_not_seeded(): void
    {
        $this->seed(UserSeeder::class);

        $user = AuthTestUser::query()->where('email', 'demo@example.com')->first();
        self::assertNotNull($user);

        self::assertFalse(NavigationNode::query()->where('key', 'root')->exists());

        $response = $this->actingAs($user, 'web')->getJson('/api/navigation');

        $response->assertOk();
        self::assertTrue(NavigationNode::query()->where('key', 'root')->exists());
        $payload = $response->json();
        self::assertIsArray($payload);
        self::assertNotEmpty($payload[0]['items'] ?? []);
    }

    public function test_navigation_hides_customers_when_module_disabled(): void
    {
        $this->seed($this->seedDefaults());

        MaestroModule::query()->where('slug', 'customers')->update(['is_enabled' => false]);

        $user = AuthTestUser::query()->where('email', 'demo@example.com')->first();
        self::assertNotNull($user);

        $response = $this->actingAs($user, 'web')->getJson('/api/navigation');

        $response->assertOk();
        $payload = $response->json();
        $keys = array_column($payload[0]['items'], 'key');
        self::assertNotContains('customers', $keys);
    }

    public function test_navigation_hides_offers_and_invoice_settings_nodes_when_modules_disabled(): void
    {
        $this->seed($this->seedDefaults());

        MaestroModule::query()
            ->whereIn('slug', ['offers', 'invoices'])
            ->update(['is_enabled' => false]);

        $user = AuthTestUser::query()->where('email', 'demo@example.com')->first();
        self::assertNotNull($user);

        $response = $this->actingAs($user, 'web')->getJson('/api/navigation');

        $response->assertOk();
        $payload = $response->json();
        $settings = collect($payload[0]['items'])->firstWhere('key', 'settings');
        self::assertIsArray($settings);

        $settingsKeys = array_column($settings['items'] ?? [], 'key');
        self::assertNotContains('settings-offers-catalog', $settingsKeys);
        self::assertNotContains('settings-offers-templates', $settingsKeys);
        self::assertNotContains('settings-invoices-vat', $settingsKeys);
    }

    public function test_superadmin_modules_forbidden_without_permission(): void
    {
        $this->seed($this->seedDefaults());

        $user = AuthTestUser::query()->where('email', 'demo@example.com')->first();
        self::assertNotNull($user);

        $guardName = PermissionGuardName::forApp();
        $role = Role::findByName('admin', $guardName);
        self::assertNotNull($role);
        $role->revokePermissionTo('platform.superadmin');
        app()[PermissionRegistrar::class]->forgetCachedPermissions();

        $response = $this->actingAs($user, 'web')->getJson('/api/superadmin/modules');

        $response->assertForbidden();
    }

    public function test_superadmin_navigation_tree_roundtrip(): void
    {
        $this->seed($this->seedDefaults());

        $user = AuthTestUser::query()->where('email', 'demo@example.com')->first();
        self::assertNotNull($user);

        $show = $this->actingAs($user, 'web')->getJson('/api/superadmin/navigation-tree');
        $show->assertOk();
        $tree = $show->json('tree');
        self::assertIsArray($tree);

        $put = $this->actingAs($user, 'web')->putJson('/api/superadmin/navigation-tree', [
            'tree' => $tree,
        ]);
        $put->assertOk();
    }
}
