<?php

namespace App\Console\Commands;

use App\Models\Menu;
use App\Models\Page;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Collection;

class CreateMenuItemsForPages extends Command
{
    protected $signature = 'menu:create-for-pages
                            {--dry-run : Run without persisting data}';

    protected $description = 'Create hierarchical menu structure for existing pages';

    /** @var array<string, int> */
    protected array $stats = [
        'total' => 0,
        'parent_menus_created' => 0,
        'child_menus_created' => 0,
        'skipped' => 0,
    ];

    // Define the menu structure
    /** @var array<string, array{slug: string, display_order: int, pages: list<string>}> */
    protected array $menuStructure = [
        'How You Can Help' => [
            'slug' => 'how-you-can-help',
            'display_order' => 3,
            'pages' => ['donations', 'wish-list'],
        ],
        'Events' => [
            'slug' => 'events',
            'display_order' => 4,
            'pages' => ['adoption-events', 'fundraising-events'],
        ],
        'Information' => [
            'slug' => 'information',
            'display_order' => 5,
            'pages' => [
                'adoption-process-and-policies',
                'fostering',
                'adoption-fees',
                'trapping-services-tnvr-program',
                'barn-cat-program',
            ],
        ],
    ];

    public function handle(): int
    {
        $this->info('Creating Menu Items for Pages');
        $this->info('================================');
        $this->newLine();

        if ($this->option('dry-run')) {
            $this->warn('DRY RUN MODE - No data will be persisted');
            $this->newLine();
        }

        $pages = Page::all();
        $this->stats['total'] = $pages->count();

        // First, create parent menus
        $this->createParentMenus();

        // Then, create menu items for pages
        $this->createPageMenuItems($pages);

        $this->displaySummary();

        return Command::SUCCESS;
    }

    protected function createParentMenus(): void
    {
        foreach ($this->menuStructure as $menuName => $config) {
            if ($this->option('dry-run')) {
                $this->info("Would create parent menu: {$menuName}");
                $this->stats['parent_menus_created']++;

                continue;
            }

            // Check if parent menu already exists
            $existingMenu = Menu::where('slug', $config['slug'])
                ->whereNull('parent_id')
                ->first();

            if ($existingMenu) {
                $this->info("Parent menu '{$menuName}' already exists");

                continue;
            }

            Menu::create([
                'name' => $menuName,
                'slug' => $config['slug'],
                'icon' => null,
                'parent_id' => null,
                'display_order' => $config['display_order'],
                'is_visible' => true,
                'requires_auth' => false,
            ]);

            $this->stats['parent_menus_created']++;
            $this->info("Created parent menu: {$menuName}");
        }

        $this->newLine();
    }

    /**
     * @param  Collection<int, Page>  $pages
     */
    protected function createPageMenuItems(Collection $pages): void
    {
        $progressBar = $this->output->createProgressBar($pages->count());
        $progressBar->setFormat(' %current%/%max% [%bar%] %percent:3s%% - %message%');

        foreach ($pages as $page) {
            $progressBar->setMessage("Processing: {$page->title}");

            // Determine if this page should be under a parent menu
            $parentMenuSlug = $this->findParentMenuForPage($page->slug);

            if ($parentMenuSlug) {
                // Create as child menu item
                $this->createChildMenuItem($page, $parentMenuSlug);
            } else {
                // Skip creating standalone menu items for pages that should be under parent menus
                $this->stats['skipped']++;
            }

            $progressBar->advance();
        }

        $progressBar->finish();
        $this->newLine(2);
    }

    protected function findParentMenuForPage(string $pageSlug): ?string
    {
        foreach ($this->menuStructure as $config) {
            if (in_array($pageSlug, $config['pages'])) {
                return $config['slug'];
            }
        }

        return null;
    }

    protected function createChildMenuItem(Page $page, string $parentMenuSlug): void
    {
        if ($this->option('dry-run')) {
            $this->stats['child_menus_created']++;

            return;
        }

        // Get parent menu
        $parentMenu = Menu::where('slug', $parentMenuSlug)->whereNull('parent_id')->first();

        if (! $parentMenu) {
            return;
        }

        // Check if a menu with this slug already exists (globally, due to unique constraint)
        $existingMenu = Menu::where('slug', $page->slug)->first();

        if ($existingMenu) {
            return;
        }

        // Get the highest display order for this parent's children
        $maxDisplayOrder = Menu::where('parent_id', $parentMenu->id)->max('display_order') ?? 0;

        Menu::create([
            'name' => $page->title,
            'slug' => $page->slug,
            'icon' => null,
            'parent_id' => $parentMenu->id,
            'display_order' => $maxDisplayOrder + 1,
            'is_visible' => $page->status === 'published',
            'requires_auth' => $page->requires_auth,
        ]);

        $this->stats['child_menus_created']++;
    }

    protected function displaySummary(): void
    {
        $this->info('Summary');
        $this->info('==================');
        $this->info("Total pages processed: {$this->stats['total']}");
        $this->info("Parent menus created: {$this->stats['parent_menus_created']}");
        $this->info("Child menu items created: {$this->stats['child_menus_created']}");
        $this->info("Skipped: {$this->stats['skipped']}");
        $this->newLine();

        if ($this->option('dry-run')) {
            $this->warn('DRY RUN - no data was persisted.');
        }
    }
}
