<?php

namespace App\Services\Authz;

use App\Models\Permissions\Role;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Spatie\Permission\PermissionRegistrar;

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

    /** 목록 */
    public static function index(array $params = [])
    {
        $tenantId = (int) app('tenant_id');
        $page = (int) ($params['page'] ?? 1);
        $size = (int) ($params['size'] ?? 10);
        $q = trim((string) ($params['q'] ?? ''));

        $query = Role::query()
            ->where('tenant_id', $tenantId)
            ->where('guard_name', self::$guard)
            ->withCount(['permissions', 'users']);

        // 검색 필터
        if ($q !== '') {
            $query->where(function ($w) use ($q) {
                $w->where('name', 'like', "%{$q}%")
                    ->orWhere('description', 'like', "%{$q}%");
            });
        }

        // 숨김 상태 필터
        if (isset($params['is_hidden'])) {
            $isHidden = filter_var($params['is_hidden'], FILTER_VALIDATE_BOOLEAN);
            $query->where('is_hidden', $isHidden);
        }

        $list = $query->orderByDesc('id')
            ->paginate($size, ['*'], 'page', $page);

        return $list;
    }

    /** 생성 */
    public static function store(array $params = [])
    {
        $tenantId = (int) app('tenant_id');
        $userId = app('api_user');

        $v = Validator::make($params, [
            'name' => [
                'required', 'string', 'max:100',
                Rule::unique('roles', 'name')->where(fn ($q) => $q
                    ->where('tenant_id', $tenantId)
                    ->where('guard_name', self::$guard)),
            ],
            'description' => 'nullable|string|max:255',
            'is_hidden' => 'sometimes|boolean',
        ]);

        if ($v->fails()) {
            return ['error' => $v->errors()->first(), 'code' => 422];
        }

        // Spatie 팀(테넌트) 컨텍스트
        app(PermissionRegistrar::class)->setPermissionsTeamId($tenantId);

        $role = Role::create([
            'tenant_id' => $tenantId,
            'guard_name' => self::$guard,
            'name' => $v->validated()['name'],
            'description' => $params['description'] ?? null,
            'is_hidden' => $params['is_hidden'] ?? false,
            'created_by' => $userId,
        ]);

        return $role->loadCount(['permissions', 'users']);
    }

    /** 단건 */
    public static function show(int $id)
    {
        $tenantId = (int) app('tenant_id');

        $role = Role::where('tenant_id', $tenantId)
            ->where('guard_name', self::$guard)
            ->withCount(['permissions', 'users'])
            ->find($id);

        if (! $role) {
            return ['error' => '역할을 찾을 수 없습니다.', 'code' => 404];
        }

        return $role;
    }

    /** 수정 */
    public static function update(int $id, array $params = [])
    {
        $tenantId = (int) app('tenant_id');
        $userId = app('api_user');

        $role = Role::where('tenant_id', $tenantId)
            ->where('guard_name', self::$guard)
            ->find($id);

        if (! $role) {
            return ['error' => '역할을 찾을 수 없습니다.', 'code' => 404];
        }

        $v = Validator::make($params, [
            'name' => [
                'sometimes', 'string', 'max:100',
                Rule::unique('roles', 'name')
                    ->where(fn ($q) => $q->where('tenant_id', $tenantId)->where('guard_name', self::$guard))
                    ->ignore($role->id),
            ],
            'description' => 'sometimes|nullable|string|max:255',
            'is_hidden' => 'sometimes|boolean',
        ]);

        if ($v->fails()) {
            return ['error' => $v->errors()->first(), 'code' => 422];
        }

        $updateData = $v->validated();
        $updateData['updated_by'] = $userId;

        $role->fill($updateData)->save();

        return $role->fresh()->loadCount(['permissions', 'users']);
    }

    /** 삭제 (Soft Delete) */
    public static function destroy(int $id)
    {
        $tenantId = (int) app('tenant_id');
        $userId = app('api_user');

        $role = Role::where('tenant_id', $tenantId)
            ->where('guard_name', self::$guard)
            ->find($id);

        if (! $role) {
            return ['error' => '역할을 찾을 수 없습니다.', 'code' => 404];
        }

        DB::transaction(function () use ($role, $userId) {
            // 권한 연결 해제
            $role->permissions()->detach();

            // Soft Delete
            $role->update(['deleted_by' => $userId]);
            $role->delete();
        });

        return 'success';
    }

    /** 통계 조회 */
    public static function stats()
    {
        $tenantId = (int) app('tenant_id');

        $baseQuery = Role::where('tenant_id', $tenantId)
            ->where('guard_name', self::$guard);

        return [
            'total' => (clone $baseQuery)->count(),
            'visible' => (clone $baseQuery)->where('is_hidden', false)->count(),
            'hidden' => (clone $baseQuery)->where('is_hidden', true)->count(),
            'with_users' => (clone $baseQuery)->has('users')->count(),
        ];
    }

    /** 활성 역할 목록 (드롭다운용) */
    public static function active()
    {
        $tenantId = (int) app('tenant_id');

        return Role::where('tenant_id', $tenantId)
            ->where('guard_name', self::$guard)
            ->where('is_hidden', false)
            ->orderBy('name')
            ->get(['id', 'name', 'description']);
    }
}
