<?php

namespace App\Models;

use Illuminate\Support\Facades\DB;
use App\Support\AdminPermissionBridge;
use App\Support\AdminPermissionInheritance;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\ValidationException;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

final class AdminRole extends Model
{
    public const ROLE_SUPER_ADMIN = 'super_admin';

    public const SCOPE_SYSTEM = 'system';

    public const SCOPE_AGENT = 'agent';

    protected $table = 'admin_roles';

    protected static function booted(): void
    {
        self::creating(function (AdminRole $role): void {
            if (($role->code ?? '') === '' && is_string($role->slug) && $role->slug !== '') {
                $role->code = $role->slug;
            }
        });
    }

    protected $fillable = [
        'slug',
        'name',
        'code',
        'description',
        'status',
        'is_system',
        'sort_order',
        'owner_agent_id',
        'delegated_from_role_id',
        'scope_type',
    ];

    protected function casts(): array
    {
        return [
            'owner_agent_id' => 'integer',
            'delegated_from_role_id' => 'integer',
            'status' => 'integer',
            'is_system' => 'boolean',
            'sort_order' => 'integer',
        ];
    }

    public function isAgentScoped(): bool
    {
        return $this->scope_type === self::SCOPE_AGENT && $this->owner_agent_id !== null;
    }

    public function isReadOnlyTemplate(): bool
    {
        return $this->delegated_from_role_id !== null;
    }

    /**
     * @return BelongsToMany<AdminMenuAction, AdminRole>
     */
    public function menuActions(): BelongsToMany
    {
        return $this->belongsToMany(
            AdminMenuAction::class,
            'admin_role_menu_actions',
            'role_id',
            'menu_action_id',
        );
    }

    /** @return BelongsToMany<AdminUser, AdminRole> */
    public function users(): BelongsToMany
    {
        return $this->belongsToMany(
            AdminUser::class,
            'admin_user_site_roles',
            'role_id',
            'admin_user_id',
        )->withPivot(['site_id', 'granted_at']);
    }

    /**
     * 由已授权的 menu_action 反推 `prd.*`（与 Registry 映射一致）。
     *
     * @return list<string>
     */
    public function legacyPermissionSlugs(): array
    {
        $codes = DB::table('admin_role_menu_actions as rma')
            ->join('admin_menu_actions as ma', 'ma.id', '=', 'rma.menu_action_id')
            ->where('rma.role_id', $this->id)
            ->where('ma.status', 1)
            ->pluck('ma.permission_code')
            ->all();

        return AdminPermissionBridge::legacySlugsGrantedByMenuActionCodes($codes);
    }

    /** 授予当前库中全部启用的 menu_action（用于超级管理员）。 */
    public function syncAllActiveMenuActions(): void
    {
        $ids = DB::table('admin_menu_actions')
            ->where('status', 1)
            ->pluck('id')
            ->map(static fn ($id): int => (int) $id)
            ->all();

        DB::table('admin_role_menu_actions')->where('role_id', $this->id)->delete();
        foreach ($ids as $mid) {
            DB::table('admin_role_menu_actions')->insert([
                'role_id' => $this->id,
                'menu_action_id' => $mid,
            ]);
        }
    }

    /**
     * @param  list<string>  $slugs
     */
    public function syncLegacyPermissionSlugs(array $slugs): void
    {
        $legacySlugs = AdminPermissionInheritance::expand(
            AdminPermissionBridge::normalizeCanonicalLegacySlugs($slugs),
        );

        $codes = [];
        foreach ($legacySlugs as $slug) {
            $codes = array_merge($codes, AdminPermissionBridge::menuActionCodesForLegacy($slug));
        }
        $codes = array_values(array_unique($codes));

        $ids = DB::table('admin_menu_actions')
            ->whereIn('permission_code', $codes)
            ->where('status', 1)
            ->pluck('id')
            ->all();

        DB::table('admin_role_menu_actions')->where('role_id', $this->id)->delete();
        foreach ($ids as $mid) {
            DB::table('admin_role_menu_actions')->insert([
                'role_id' => $this->id,
                'menu_action_id' => (int) $mid,
            ]);
        }

        $granted = $this->legacyPermissionSlugs();
        $missing = array_values(array_diff($legacySlugs, $granted));
        if ($missing !== []) {
            throw ValidationException::withMessages([
                'permission_slugs' => [
                    'permission_catalog_incomplete: '.implode(', ', $missing)
                    .' (run: php artisan migrate && php artisan lottery:admin-auth-sync --audit)',
                ],
            ]);
        }
    }

    public function assignedUserCount(): int
    {
        $agentCount = (int) DB::table('admin_user_agent_roles')
            ->where('role_id', $this->id)
            ->distinct()
            ->count('admin_user_id');

        if ($this->isAgentScoped()) {
            return $agentCount;
        }

        return (int) DB::table('admin_user_site_roles')
            ->where('role_id', $this->id)
            ->distinct()
            ->count('admin_user_id');
    }
}
