<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class MenuItem extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'title',
        'slug',
        'description',
        'keywords',
        'icon',
        'parent_id',
        'content_page_id',
        'action_type',
        'action_data',
        'sort_order',
        'is_active',
        'is_visible',
        'roles',
        'metadata',
    ];

    protected $casts = [
        'is_active' => 'boolean',
        'is_visible' => 'boolean',
        'roles' => 'array',
        'action_data' => 'array',
        'metadata' => 'array',
        'sort_order' => 'integer',
    ];

    /**
     * Action types for menu items
     */
    public const ACTION_SHOW_SUBMENU = 'show_submenu';
    public const ACTION_SHOW_PAGE = 'show_page';
    public const ACTION_EXTERNAL_URL = 'external_url';
    public const ACTION_CALLBACK = 'callback';
    public const ACTION_COMMAND = 'command';

    /**
     * Get the parent menu item
     */
    public function parent(): BelongsTo
    {
        return $this->belongsTo(MenuItem::class, 'parent_id');
    }

    /**
     * Get child menu items
     */
    public function children(): HasMany
    {
        return $this->hasMany(MenuItem::class, 'parent_id')->orderBy('sort_order');
    }

    /**
     * Get associated content page
     */
    public function contentPage(): BelongsTo
    {
        return $this->belongsTo(ContentPage::class, 'content_page_id');
    }

    /**
     * Scope for active menu items
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope for visible menu items
     */
    public function scopeVisible($query)
    {
        return $query->where('is_visible', true);
    }

    /**
     * Scope for root menu items
     */
    public function scopeRoot($query)
    {
        return $query->whereNull('parent_id');
    }

    /**
     * Scope for menu items by depth level
     */
    public function scopeByLevel($query, int $level)
    {
        if ($level === 0) {
            return $query->whereNull('parent_id');
        }

        // For deeper levels, we'd need a more complex query
        // This is a simplified version
        return $query->whereHas('parent', function ($q) use ($level) {
            if ($level === 1) {
                $q->whereNull('parent_id');
            }
        });
    }

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

    /**
     * Check if user has access to this menu item
     */
    public function hasAccess(?User $user = null): bool
    {
        // If no roles specified, everyone has access
        if (empty($this->roles)) {
            return true;
        }

        // If no user provided, deny access to role-restricted items
        if (!$user) {
            return false;
        }

        // Check if user role is in allowed roles
        return in_array($user->role, $this->roles);
    }

    /**
     * Get menu breadcrumb path
     */
    public function getBreadcrumb(): array
    {
        $breadcrumb = [];
        $current = $this;

        while ($current) {
            array_unshift($breadcrumb, [
                'id' => $current->id,
                'title' => $current->title,
                'slug' => $current->slug,
            ]);
            $current = $current->parent;
        }

        return $breadcrumb;
    }

    /**
     * Get menu tree structure
     */
    public static function getTree(?int $parentId = null): array
    {
        $items = self::active()
            ->visible()
            ->where('parent_id', $parentId)
            ->orderBy('sort_order')
            ->get();

        $tree = [];
        foreach ($items as $item) {
            $node = $item->toArray();
            $node['children'] = self::getTree($item->id);
            $tree[] = $node;
        }

        return $tree;
    }

    /**
     * Get all menu items as a flat list with indentation
     */
    public static function getFlatList(?int $parentId = null, int $level = 0): array
    {
        $items = self::where('parent_id', $parentId)
            ->orderBy('sort_order')
            ->get();

        $list = [];
        foreach ($items as $item) {
            $item->level = $level;
            $item->indented_title = str_repeat('— ', $level) . $item->title;
            $list[] = $item;
            
            // Recursively add children
            $children = self::getFlatList($item->id, $level + 1);
            $list = array_merge($list, $children);
        }

        return $list;
    }

    /**
     * Get the full menu path (slug path)
     */
    public function getFullSlugAttribute(): string
    {
        $slugs = [];
        $current = $this;

        while ($current) {
            array_unshift($slugs, $current->slug);
            $current = $current->parent;
        }

        return implode('/', $slugs);
    }

    /**
     * Get action data as formatted string for display
     */
    public function getActionDisplayAttribute(): string
    {
        return match($this->action_type) {
            self::ACTION_SHOW_PAGE => 'Show Page: ' . ($this->contentPage?->title ?? 'Not set'),
            self::ACTION_SHOW_SUBMENU => 'Show Submenu',
            self::ACTION_EXTERNAL_URL => 'External URL: ' . ($this->action_data['url'] ?? 'Not set'),
            self::ACTION_CALLBACK => 'Callback: ' . ($this->action_data['callback'] ?? 'Not set'),
            self::ACTION_COMMAND => 'Command: ' . ($this->action_data['command'] ?? 'Not set'),
            default => 'Unknown action',
        };
    }

    /**
     * Boot model events
     */
    protected static function boot()
    {
        parent::boot();

        // Automatically generate slug from title if not provided
        static::creating(function ($menuItem) {
            if (empty($menuItem->slug)) {
                $menuItem->slug = \Str::slug($menuItem->title);
            }
        });

        // Ensure unique slug within the same parent
        static::saving(function ($menuItem) {
            $count = self::where('parent_id', $menuItem->parent_id)
                ->where('slug', $menuItem->slug)
                ->where('id', '!=', $menuItem->id)
                ->count();

            if ($count > 0) {
                $menuItem->slug = $menuItem->slug . '-' . time();
            }
        });
    }
}