<?php

namespace FluxCms\Components\Livewire\Frontend;

use FluxCms\Core\Models\Navigation;
use Illuminate\Support\Collection;
use Livewire\Component;

class NavigationRenderer extends Component
{
    public string $domainKey;

    public string $navigationName;

    public ?Navigation $navigation = null;

    public Collection $navigationItems;

    public string $currentUrl = '';

    public array $classes = [];

    public bool $showInactive = false;

    public function mount(
        string $domainKey,
        string $navigationName,
        array $classes = [],
        bool $showInactive = false
    ) {
        $this->domainKey = $domainKey;
        $this->navigationName = $navigationName;
        $this->classes = $classes;
        $this->showInactive = $showInactive;
        $this->currentUrl = request()->url();
        $this->loadNavigation();
    }

    public function render()
    {
        return view('flux-cms-components::livewire.frontend.navigation-renderer');
    }

    /**
     * Load navigation and items
     */
    protected function loadNavigation()
    {
        $this->navigation = Navigation::forDomain($this->domainKey)
            ->byName($this->navigationName, $this->domainKey)
            ->active()
            ->first();

        if ($this->navigation) {
            $this->navigationItems = $this->navigation->getHierarchicalItems();

            // Filter inactive items if needed
            if (! $this->showInactive) {
                $this->navigationItems = $this->navigationItems->where('is_active', true);
            }
        } else {
            $this->navigationItems = collect();
        }
    }

    /**
     * Check if navigation item is active
     */
    public function isActive($item): bool
    {
        return $item->isActive($this->currentUrl);
    }

    /**
     * Get URL for navigation item
     */
    public function getItemUrl($item): string
    {
        return $item->getUrl(app()->getLocale());
    }

    /**
     * Get label for navigation item
     */
    public function getItemLabel($item): string
    {
        $locale = app()->getLocale();

        return $item->getTranslation('label', $locale);
    }

    /**
     * Check if item has children
     */
    public function hasChildren($item): bool
    {
        return $item->children->isNotEmpty();
    }

    /**
     * Get children of item
     */
    public function getChildren($item): Collection
    {
        if (! $this->showInactive) {
            return $item->children->where('is_active', true);
        }

        return $item->children;
    }

    /**
     * Check if item should open in new tab
     */
    public function opensInNewTab($item): bool
    {
        return $item->opens_in_new_tab;
    }

    /**
     * Get CSS classes for navigation container
     */
    public function getNavigationClasses(): string
    {
        $defaultClasses = ['flux-cms-navigation', 'navigation-'.$this->navigationName];
        $allClasses = array_merge($defaultClasses, $this->classes);

        return implode(' ', $allClasses);
    }

    /**
     * Get CSS classes for navigation item
     */
    public function getItemClasses($item, bool $isChild = false): string
    {
        $classes = ['nav-item'];

        if ($isChild) {
            $classes[] = 'nav-item--child';
        }

        if ($this->isActive($item)) {
            $classes[] = 'nav-item--active';
        }

        if ($this->hasChildren($item)) {
            $classes[] = 'nav-item--has-children';
        }

        if (! $item->is_active) {
            $classes[] = 'nav-item--inactive';
        }

        return implode(' ', $classes);
    }

    /**
     * Get link attributes
     */
    public function getLinkAttributes($item): array
    {
        $attributes = [
            'href' => $this->getItemUrl($item),
            'class' => 'nav-link',
        ];

        if ($this->opensInNewTab($item)) {
            $attributes['target'] = '_blank';
            $attributes['rel'] = 'noopener noreferrer';
        }

        if ($this->isActive($item)) {
            $attributes['class'] .= ' nav-link--active';
            $attributes['aria-current'] = 'page';
        }

        return $attributes;
    }

    /**
     * Render link attributes as string
     */
    public function renderLinkAttributes($item): string
    {
        $attributes = $this->getLinkAttributes($item);
        $attributeStrings = [];

        foreach ($attributes as $key => $value) {
            $attributeStrings[] = $key.'="'.htmlspecialchars($value).'"';
        }

        return implode(' ', $attributeStrings);
    }

    /**
     * Get breadcrumbs for current page
     */
    public function getBreadcrumbs(): Collection
    {
        $breadcrumbs = collect();

        foreach ($this->navigationItems as $item) {
            if ($item->isActive($this->currentUrl)) {
                $breadcrumbs = $item->getBreadcrumbs();
                break;
            }

            // Check children recursively
            $childBreadcrumbs = $this->findBreadcrumbsInChildren($item);
            if ($childBreadcrumbs->isNotEmpty()) {
                $breadcrumbs = $childBreadcrumbs;
                break;
            }
        }

        return $breadcrumbs;
    }

    /**
     * Find breadcrumbs in children recursively
     */
    protected function findBreadcrumbsInChildren($item): Collection
    {
        foreach ($item->children as $child) {
            if ($child->isActive($this->currentUrl)) {
                return $child->getBreadcrumbs();
            }

            $childBreadcrumbs = $this->findBreadcrumbsInChildren($child);
            if ($childBreadcrumbs->isNotEmpty()) {
                return $childBreadcrumbs;
            }
        }

        return collect();
    }

    /**
     * Check if navigation exists and has items
     */
    public function hasNavigation(): bool
    {
        return $this->navigation !== null && $this->navigationItems->isNotEmpty();
    }

    /**
     * Get navigation display name
     */
    public function getNavigationDisplayName(): string
    {
        if (! $this->navigation) {
            return '';
        }

        $locale = app()->getLocale();

        return $this->navigation->getTranslation('display_name', $locale);
    }
}
