<?php

namespace App\Observers;

use App\Models\Commons\Menu; // ← 실제 경로 확인
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\PermissionRegistrar;

class MenuObserver
{
    protected function actions(): array
    {
        // config/authz.php 에서 오버라이드 가능 (없으면 기본값)
        return config('authz.menu_actions', ['view', 'create', 'update', 'delete', 'approve']);
    }

    protected string $guard = 'api';

    public function created(Menu $menu): void
    {
        if (! $this->shouldHandle($menu)) {
            return;
        }

        $this->setTeam((int) $menu->tenant_id);
        $this->ensurePermissions($menu);
        $this->forgetCacheAfterCommit();
    }

    public function updated(Menu $menu): void
    {
        // 메뉴 ID 기반: 권한 이름 변경 불필요
        // 필요 시, 기본 롤 자동 부여/회수 같은 정책을 이곳에…
    }

    public function deleted(Menu $menu): void
    {
        if (! $this->shouldHandle($menu)) {
            return;
        }

        $this->setTeam((int) $menu->tenant_id);
        $this->removePermissions($menu);
        $this->forgetCacheAfterCommit();
    }

    public function restored(Menu $menu): void
    {
        if (! $this->shouldHandle($menu)) {
            return;
        }

        $this->setTeam((int) $menu->tenant_id);
        $this->ensurePermissions($menu);
        $this->forgetCacheAfterCommit();
    }

    public function forceDeleted(Menu $menu): void
    {
        if (! $this->shouldHandle($menu)) {
            return;
        }

        $this->setTeam((int) $menu->tenant_id);
        $this->removePermissions($menu);
        $this->forgetCacheAfterCommit();
    }

    /** teams 사용 시 tenant_id 없는 공용 메뉴는 스킵하는 게 안전 */
    protected function shouldHandle(Menu $menu): bool
    {
        return ! is_null($menu->tenant_id);
    }

    protected function setTeam(int $tenantId): void
    {
        app(PermissionRegistrar::class)->setPermissionsTeamId($tenantId);
    }

    protected function ensurePermissions(Menu $menu): void
    {
        $actions = $this->actions();
        $permissionsData = [];
        $now = now();

        foreach ($actions as $act) {
            $permissionsData[] = [
                'tenant_id' => (int) $menu->tenant_id,
                'guard_name' => $this->guard,
                'name' => "menu:{$menu->id}.{$act}",
                'created_at' => $now,
                'updated_at' => $now,
            ];
        }

        // Bulk insert using insertOrIgnore to avoid duplicate errors
        DB::table('permissions')->insertOrIgnore($permissionsData);
    }

    protected function removePermissions(Menu $menu): void
    {
        Permission::where('tenant_id', (int) $menu->tenant_id)
            ->where('guard_name', $this->guard)
            ->where(function ($q) use ($menu) {
                foreach ($this->actions() as $act) {
                    $q->orWhere('name', "menu:{$menu->id}.{$act}");
                }
            })->delete();
    }

    protected function forgetCache(): void
    {
        app(PermissionRegistrar::class)->forgetCachedPermissions();
    }

    protected function forgetCacheAfterCommit(): void
    {
        // Defer cache clearing until after transaction commits
        DB::afterCommit(function () {
            app(PermissionRegistrar::class)->forgetCachedPermissions();
        });
    }
}
