<?php

namespace Tests\Feature;

use Filament\Clusters\Cluster;
use Filament\Facades\Filament;
use Filament\Pages\Page as FilamentPage;
use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;

class FilamentPanelNavigationTest extends TestCase
{
    use RefreshDatabase;

    public function test_all_panel_resources_and_pages_build_navigation_items(): void
    {
        $panels = Filament::getPanels();

        $this->assertNotEmpty($panels);

        foreach ($panels as $panel) {
            Filament::setCurrentPanel($panel);
            Filament::bootCurrentPanel();

            if ($panel->hasTenancy()) {
                $tenantModel = $panel->getTenantModel();
                $this->assertNotNull($tenantModel, $panel->getId());

                $userModel = \App\Models\User::class;
                $user = $userModel::factory()->create();
                Filament::auth()->login($user);

                $tenant = $tenantModel::factory()->create();
                Filament::setTenant($tenant);
            }

            foreach ($panel->getResources() as $resource) {
                $this->assertTrue(is_subclass_of($resource, Resource::class), $resource);
                $this->assertIsArray($resource::getPages(), $resource);
                $this->assertIsArray($resource::getNavigationItems(), $resource);
            }

            foreach ($panel->getPages() as $page) {
                if (! is_subclass_of($page, FilamentPage::class)) {
                    continue;
                }

                if (! $page::shouldRegisterNavigation()) {
                    continue;
                }

                if (str_contains($page::getRoutePath($panel), '{')) {
                    continue;
                }

                $this->assertIsArray($page::getNavigationItems(), $page);
            }

            foreach ($panel->getClusters() as $cluster) {
                $this->assertTrue(is_subclass_of($cluster, Cluster::class), $cluster);
                $this->assertIsArray($cluster::getNavigationItems(), $cluster);
            }

            Filament::setTenant(null, true);
        }
    }

    public function test_all_resource_index_pages_render_without_errors(): void
    {
        $panels = Filament::getPanels();

        $this->assertNotEmpty($panels);

        foreach ($panels as $panel) {
            Filament::setCurrentPanel($panel);
            Filament::bootCurrentPanel();

            $userModel = \App\Models\User::class;
            $user = $userModel::factory()->create();
            Filament::auth()->login($user);

            if ($panel->hasTenancy()) {
                $tenantModel = $panel->getTenantModel();
                $this->assertNotNull($tenantModel, $panel->getId());

                $tenant = $tenantModel::factory()->create();
                Filament::setTenant($tenant);
            }

            foreach ($panel->getResources() as $resource) {
                $resource::skipAuthorization();

                $pages = $resource::getPages();
                $this->assertNotEmpty($pages, $resource);

                $registration = $pages['index'] ?? reset($pages);
                $pageClass = $registration instanceof PageRegistration ? $registration->getPage() : $registration;

                Livewire::test($pageClass)
                    ->assertStatus(200);
            }

            Filament::auth()->logout();
            Filament::setTenant(null, true);
        }
    }
}
