<?php

namespace App\Services\Authz;

use App\Models\Members\User;
use App\Models\Permissions\Role;
use Spatie\Permission\PermissionRegistrar;

class UserRoleService
{
    protected static string $guard = 'api';

    /** 팀(테넌트) 컨텍스트 고정 */
    protected static function setTeam(int $tenantId): void
    {
        app(PermissionRegistrar::class)->setPermissionsTeamId($tenantId);
    }

    /** 권한 캐시 무효화 */
    protected static function invalidateCache(int $tenantId): void
    {
        AccessService::bumpVersion($tenantId);
        app(PermissionRegistrar::class)->forgetCachedPermissions();
    }

    /** 유저 로드 (존재 체크) */
    protected static function loadUserOrError(int $userId): ?User
    {
        return User::find($userId);
    }

    /** 입력으로 받은 role_names[] 또는 role_ids[] → 실제 역할 이름 배열로 변환(검증 포함) */
    protected static function resolveRoleNames(int $tenantId, array $params): array
    {
        $names = [];

        // A) role_names[] 직접
        if (! empty($params['role_names']) && is_array($params['role_names'])) {
            foreach ($params['role_names'] as $n) {
                if (is_string($n) && $n !== '') {
                    $names[] = trim($n);
                }
            }
        }

        // B) role_ids[] → 이름으로 변환
        if (! empty($params['role_ids']) && is_array($params['role_ids'])) {
            $ids = array_values(array_unique(array_map('intval', $params['role_ids'])));
            if (! empty($ids)) {
                $rows = Role::query()
                    ->where('tenant_id', $tenantId)
                    ->where('guard_name', self::$guard)
                    ->whereIn('id', $ids)
                    ->pluck('name')
                    ->all();
                $names = array_merge($names, $rows);
            }
        }

        // 정제
        $names = array_values(array_unique(array_filter($names)));

        // 존재 확인
        if (! empty($names)) {
            Role::query()
                ->where('tenant_id', $tenantId)
                ->where('guard_name', self::$guard)
                ->whereIn('name', $names)
                ->count();
        }

        return $names;
    }

    /** 목록 */
    public static function list(int $userId)
    {
        $tenantId = (int) app('tenant_id');

        $user = self::loadUserOrError($userId);
        if (! $user) {
            return ['error' => __('error.role.user_not_found'), 'code' => 404];
        }

        self::setTeam($tenantId);

        $builder = $user->roles()
            ->where('roles.tenant_id', $tenantId)
            ->where('roles.guard_name', self::$guard)
            ->select(['roles.id', 'roles.tenant_id', 'roles.name', 'roles.description', 'roles.guard_name', 'roles.created_at', 'roles.updated_at'])
            ->orderBy('roles.id', 'desc');

        return $builder->get();
    }

    /** 부여 (중복 무시) */
    public static function grant(int $userId, array $params = [])
    {
        $tenantId = (int) app('tenant_id');

        $user = self::loadUserOrError($userId);
        if (! $user) {
            return ['error' => __('error.role.user_not_found'), 'code' => 404];
        }

        self::setTeam($tenantId);

        $names = self::resolveRoleNames($tenantId, $params);
        if (empty($names)) {
            return ['error' => __('error.role.no_valid_roles'), 'code' => 422];
        }

        $user->assignRole($names);

        self::invalidateCache($tenantId);

        return 'success';
    }

    /** 회수 (없는 건 무시) */
    public static function revoke(int $userId, array $params = [])
    {
        $tenantId = (int) app('tenant_id');

        $user = self::loadUserOrError($userId);
        if (! $user) {
            return ['error' => __('error.role.user_not_found'), 'code' => 404];
        }

        self::setTeam($tenantId);

        $names = self::resolveRoleNames($tenantId, $params);
        if (empty($names)) {
            return ['error' => __('error.role.no_valid_roles'), 'code' => 422];
        }

        $user->removeRole($names);

        self::invalidateCache($tenantId);

        return 'success';
    }

    /** 동기화(완전 교체) */
    public static function sync(int $userId, array $params = [])
    {
        $tenantId = (int) app('tenant_id');

        $user = self::loadUserOrError($userId);
        if (! $user) {
            return ['error' => __('error.role.user_not_found'), 'code' => 404];
        }

        self::setTeam($tenantId);

        $names = self::resolveRoleNames($tenantId, $params);
        if (empty($names)) {
            return ['error' => __('error.role.no_valid_roles'), 'code' => 422];
        }

        $user->syncRoles($names);

        self::invalidateCache($tenantId);

        return 'success';
    }
}
