<?php

namespace App\Services;

use App\Models\Members\User;
use App\Models\Tenants\Department;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Role as SpatieRole;

class PermissionService extends Service
{
    /**
     * 메뉴 권한 매트릭스 조회
     * $scope: 'department' | 'role' | 'user'
     */
    public function getMenuMatrix(int $id, string $scope, array $params = []): array
    {
        // 0) 강제 테넌트 (없으면 400)
        $tenantId = $this->tenantId();

        // 1) 대상 유효성 & model_type 결정
        $modelType = $this->resolveModelType($id, $scope);
        if (! $modelType) {
            return ['success' => false, 'message' => '대상 리소스를 찾을 수 없습니다.', 'data' => null];
        }

        // 2) 메뉴 목록
        $menus = DB::table('menus')
            ->select('id', 'parent_id', 'name', 'url', 'sort_order')
            ->orderBy('sort_order')->orderBy('id')
            ->get();

        // 3) 권한 정의 (permissions.name = "menu:{menuId}.{action}")
        $perms = DB::table('permissions')
            ->select('id', 'name', 'guard_name')
            ->where('guard_name', 'api')
            ->where('name', 'like', 'menu:%')
            ->get();

        $permMap = []; // [menuId][action] => ['id','guard','code']
        foreach ($perms as $p) {
            if (preg_match('/^menu:(\d+)\.([a-z_]+)$/', $p->name, $m)) {
                $permMap[(int) $m[1]][$m[2]] = [
                    'id' => (int) $p->id,
                    'guard' => $p->guard_name,
                    'code' => $p->name,
                ];
            }
        }

        // 4) 대상의 허용/차단 집합
        $allows = DB::table('model_has_permissions')
            ->where('tenant_id', $tenantId)               // ★ 강제
            ->where('model_type', $modelType)
            ->where('model_id', $id)
            ->pluck('permission_id')->all();
        $allowSet = array_fill_keys($allows, true);

        $denies = DB::table('permission_overrides')
            ->where('tenant_id', $tenantId)               // ★ 강제
            ->where('model_type', $modelType)
            ->where('model_id', $id)
            ->where('effect', -1)
            ->pluck('permission_id')->all();
        $denySet = array_fill_keys($denies, true);

        // 5) 트리 + 액션 상태 구성
        $actions = ['view', 'create', 'update', 'delete', 'approve'];
        $byId = [];
        foreach ($menus as $m) {
            $node = [
                'menu_id' => (int) $m->id,
                'parent_id' => $m->parent_id ? (int) $m->parent_id : null,
                'name' => $m->name,
                'url' => $m->url,
                'type' => 'system',
                'children' => [],
                'actions' => [],
            ];
            foreach ($actions as $a) {
                $perm = $permMap[$m->id][$a] ?? null;
                if ($perm) {
                    $pid = $perm['id'];
                    $state = isset($denySet[$pid]) ? 'deny'
                        : (isset($allowSet[$pid]) ? 'allow' : 'none');
                    $node['actions'][$a] = [
                        'permission_id' => $pid,
                        'permission_code' => $perm['code'],
                        'guard_name' => $perm['guard'],
                        'state' => $state,
                        'is_allowed' => $state === 'allow' ? 1 : 0,
                    ];
                } else {
                    $node['actions'][$a] = null;
                }
            }
            $byId[$m->id] = $node;
        }

        // 트리 결합
        $roots = [];
        foreach ($byId as $key => &$node) {
            if ($node['parent_id'] && isset($byId[$node['parent_id']])) {
                $byId[$node['parent_id']]['children'][] = &$node;
            } else {
                $roots[] = &$node;
            }
        }
        unset($node);

        return [
            'success' => true,
            'message' => $this->titleByScope($scope).' 성공',
            'data' => [
                'actions' => $actions,
                'tree' => $roots,
            ],
        ];
    }

    /** 스코프별 대상 존재 확인 후 model_type(FQCN)만 반환 */
    private function resolveModelType(int $id, string $scope): ?string
    {
        return match ($scope) {
            'department' => Department::query()->find($id) ? Department::class : null,
            'role' => SpatieRole::query()->find($id) ? SpatieRole::class : null,
            'user' => User::query()->find($id) ? User::class : null,
            default => null,
        };
    }

    private function titleByScope(string $scope): string
    {
        return match ($scope) {
            'department' => '부서 메뉴 권한 매트릭스 조회',
            'role' => '역할 메뉴 권한 매트릭스 조회',
            'user' => '유저 메뉴 권한 매트릭스 조회',
            default => '메뉴 권한 매트릭스 조회',
        };
    }
}
