<?php

namespace App\Models\Commons;

use App\Models\Scopes\TenantScope;
use App\Traits\BelongsToTenant;
use App\Traits\ModelTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * @mixin IdeHelperMenu
 */
class Menu extends Model
{
    use BelongsToTenant, ModelTrait, SoftDeletes;

    protected $fillable = [
        'tenant_id', 'parent_id', 'global_menu_id', 'name', 'url', 'is_active', 'sort_order',
        'hidden', 'is_external', 'external_url', 'icon', 'is_customized', 'options',
        'created_by', 'updated_by', 'deleted_by',
    ];

    protected $hidden = [
        'created_by',
        'updated_by',
        'deleted_by',
        'deleted_at',
    ];

    protected $casts = [
        'is_active' => 'boolean',
        'hidden' => 'boolean',
        'is_external' => 'boolean',
        'is_customized' => 'boolean',
        'options' => 'array',
    ];

    /**
     * 동기화 비교 대상 필드
     */
    public static function getSyncFields(): array
    {
        return ['name', 'url', 'icon', 'sort_order', 'is_active', 'hidden', 'is_external', 'external_url', 'options'];
    }

    // ============================================================
    // Options JSON 헬퍼 메서드
    // ============================================================

    /**
     * options에서 특정 키 값 조회
     */
    public function getOption(string $key, mixed $default = null): mixed
    {
        return data_get($this->options, $key, $default);
    }

    /**
     * options에 특정 키 값 설정
     */
    public function setOption(string $key, mixed $value): static
    {
        $options = $this->options ?? [];
        data_set($options, $key, $value);
        $this->options = $options;

        return $this;
    }

    /**
     * 라우트명 조회 (mng, api, react 등에서 사용)
     */
    public function getRouteName(): ?string
    {
        return $this->getOption('route_name');
    }

    /**
     * 메뉴 섹션 조회 (main, tools, labs 등)
     */
    public function getSection(): string
    {
        return $this->getOption('section', 'main');
    }

    /**
     * 메뉴 타입 조회 (normal, tool, lab 등)
     */
    public function getMenuType(): string
    {
        return $this->getOption('menu_type', 'normal');
    }

    /**
     * 필요 역할 조회
     */
    public function getRequiresRole(): ?string
    {
        return $this->getOption('requires_role');
    }

    /**
     * 특정 역할이 필요한지 확인
     */
    public function requiresRole(?string $role = null): bool
    {
        $requiredRole = $this->getRequiresRole();

        if ($requiredRole === null) {
            return false;
        }

        if ($role === null) {
            return true;
        }

        return $requiredRole === $role;
    }

    /**
     * Blade 컴포넌트명 조회
     */
    public function getBladeComponent(): ?string
    {
        return $this->getOption('blade_component');
    }

    /**
     * CSS 클래스 조회
     */
    public function getCssClass(): ?string
    {
        return $this->getOption('css_class');
    }

    /**
     * meta 데이터 조회 (앱별 커스텀 데이터)
     */
    public function getMeta(?string $key = null, mixed $default = null): mixed
    {
        if ($key === null) {
            return $this->getOption('meta', []);
        }

        return $this->getOption("meta.{$key}", $default);
    }

    /**
     * meta 데이터 설정
     */
    public function setMeta(string $key, mixed $value): static
    {
        return $this->setOption("meta.{$key}", $value);
    }

    public function parent()
    {
        return $this->belongsTo(Menu::class, 'parent_id');
    }

    public function children()
    {
        return $this->hasMany(Menu::class, 'parent_id');
    }

    public function tenant()
    {
        return $this->belongsTo(\App\Models\Tenants\Tenant::class, 'tenant_id');
    }

    /**
     * 원본 글로벌 메뉴 (복제된 메뉴인 경우)
     */
    public function globalMenu()
    {
        return $this->belongsTo(GlobalMenu::class, 'global_menu_id');
    }

    /**
     * 글로벌 메뉴에서 복제된 메뉴인지 확인
     */
    public function isClonedFromGlobal(): bool
    {
        return ! is_null($this->global_menu_id);
    }

    /**
     * 테넌트가 커스터마이징 했는지 확인
     */
    public function isCustomized(): bool
    {
        return (bool) $this->is_customized;
    }

    /**
     * 글로벌 메뉴 스코프 (tenant_id가 NULL인 것)
     */
    public function scopeGlobal($query)
    {
        return $query->withoutGlobalScope(TenantScope::class)
            ->whereNull('tenant_id');
    }

    /**
     * 활성 메뉴 스코프
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * 표시되는 메뉴 스코프 (hidden=false)
     */
    public function scopeVisible($query)
    {
        return $query->where('hidden', false);
    }

    /**
     * 최상위 메뉴 스코프 (parent_id가 NULL인 것)
     */
    public function scopeRoots($query)
    {
        return $query->whereNull('parent_id');
    }

    /**
     * 공유(NULL) + 현재 테넌트 모두 포함해서 조회
     * (SoftDeletes 글로벌 스코프는 그대로 유지)
     */
    public function scopeWithShared($query, ?int $tenantId = null)
    {
        $tenantId = $tenantId ?? app('tenant_id');

        return $query
            ->withoutGlobalScope(TenantScope::class)
            ->where(function ($w) use ($tenantId) {
                if (is_null($tenantId)) {
                    $w->whereNull('tenant_id');
                } else {
                    $w->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
                }
            });
    }
}
