<?php

namespace App\Services;

use App\Models\Permission;
use App\Models\Role;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;

class RoleService
{
    /**
     * 역할 목록 조회 (페이지네이션)
     */
    public function getRoles(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $tenantId = session('selected_tenant_id');

        $query = Role::query()->withCount('permissions');

        // Guard 필터링 (선택된 경우에만)
        if (! empty($filters['guard_name'])) {
            $query->where('guard_name', $filters['guard_name']);
        }

        // 전체 보기일 때 tenant 정보 로드
        if (! $tenantId || $tenantId === 'all') {
            $query->with('tenant');
        }

        // Tenant 필터링 (선택된 경우에만)
        if ($tenantId && $tenantId !== 'all') {
            $query->where('tenant_id', $tenantId);
        }

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

        // 정렬
        $sortBy = $filters['sort_by'] ?? 'id';
        $sortDirection = $filters['sort_direction'] ?? 'desc';
        $query->orderBy($sortBy, $sortDirection);

        return $query->paginate($perPage);
    }

    /**
     * 특정 역할 조회
     */
    public function getRoleById(int $id): ?Role
    {
        $tenantId = session('selected_tenant_id');

        $query = Role::query()->with('permissions');

        // Tenant 필터링 (선택된 경우에만)
        if ($tenantId && $tenantId !== 'all') {
            $query->where('tenant_id', $tenantId);
        }

        return $query->find($id);
    }

    /**
     * 역할 생성
     */
    public function createRole(array $data): Role
    {
        $tenantId = session('selected_tenant_id');
        $effectiveTenantId = ($tenantId && $tenantId !== 'all') ? $tenantId : null;
        $guardName = $data['guard_name'] ?? 'api';

        $role = Role::create([
            'tenant_id' => $effectiveTenantId,
            'guard_name' => $guardName,
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
        ]);

        // 메뉴 권한 동기화 (있는 경우)
        if (! empty($data['menu_permissions'])) {
            $this->syncMenuPermissions($role, $data['menu_permissions'], $effectiveTenantId, $guardName);
        }

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

    /**
     * 역할 수정
     */
    public function updateRole(int $id, array $data): bool
    {
        $role = $this->getRoleById($id);

        if (! $role) {
            return false;
        }

        $tenantId = session('selected_tenant_id');
        $effectiveTenantId = ($tenantId && $tenantId !== 'all') ? $tenantId : null;
        $guardName = $data['guard_name'] ?? $role->guard_name;

        $updated = $role->update([
            'name' => $data['name'] ?? $role->name,
            'guard_name' => $guardName,
            'description' => $data['description'] ?? $role->description,
        ]);

        // 메뉴 권한 동기화 (있는 경우)
        if (isset($data['menu_permissions'])) {
            $this->syncMenuPermissions($role, $data['menu_permissions'], $effectiveTenantId, $guardName);
        }

        return $updated;
    }

    /**
     * 메뉴 권한 동기화
     */
    protected function syncMenuPermissions(Role $role, array $menuPermissions, ?int $tenantId, string $guardName): void
    {
        // 기존 메뉴 권한 모두 제거
        DB::table('role_has_permissions')
            ->where('role_id', $role->id)
            ->whereIn('permission_id', function ($query) use ($guardName) {
                $query->select('id')
                    ->from('permissions')
                    ->where('guard_name', $guardName)
                    ->where('name', 'like', 'menu:%');
            })
            ->delete();

        // 새로운 권한 부여
        foreach ($menuPermissions as $menuId => $types) {
            if (! is_array($types)) {
                continue;
            }

            foreach ($types as $type) {
                $permissionName = "menu:{$menuId}.{$type}";

                // 권한 생성 또는 조회
                $permission = Permission::firstOrCreate(
                    ['name' => $permissionName, 'guard_name' => $guardName, 'tenant_id' => $tenantId],
                    ['created_by' => auth()->id()]
                );

                // 권한 부여
                $exists = DB::table('role_has_permissions')
                    ->where('role_id', $role->id)
                    ->where('permission_id', $permission->id)
                    ->exists();

                if (! $exists) {
                    DB::table('role_has_permissions')->insert([
                        'role_id' => $role->id,
                        'permission_id' => $permission->id,
                    ]);
                }
            }
        }
    }

    /**
     * 역할 삭제
     */
    public function deleteRole(int $id): bool
    {
        $role = $this->getRoleById($id);

        if (! $role) {
            return false;
        }

        // 권한 연결 해제
        $role->permissions()->detach();

        // 사용자 연결은 FK CASCADE가 자동 처리 (model_has_roles.role_id → ON DELETE CASCADE)

        return $role->delete();
    }

    /**
     * 역할 이름 중복 체크
     */
    public function isNameExists(string $name, ?int $excludeId = null): bool
    {
        $tenantId = session('selected_tenant_id');

        $query = Role::where('guard_name', 'web')
            ->where('name', $name);

        if ($tenantId && $tenantId !== 'all') {
            $query->where('tenant_id', $tenantId);
        }

        if ($excludeId) {
            $query->where('id', '!=', $excludeId);
        }

        return $query->exists();
    }

    /**
     * 활성 역할 목록 (드롭다운용)
     */
    public function getActiveRoles(): Collection
    {
        $tenantId = session('selected_tenant_id');

        $query = Role::query()->where('guard_name', 'web');

        // Tenant 필터링 (선택된 경우에만)
        if ($tenantId && $tenantId !== 'all') {
            $query->where('tenant_id', $tenantId);
        }

        return $query->orderBy('name')->get(['id', 'name', 'description']);
    }

    /**
     * 역할 통계
     */
    public function getRoleStats(): array
    {
        $tenantId = session('selected_tenant_id');

        $baseQuery = Role::query()->where('guard_name', 'web');

        // Tenant 필터링 (선택된 경우에만)
        if ($tenantId && $tenantId !== 'all') {
            $baseQuery->where('tenant_id', $tenantId);
        }

        return [
            'total' => (clone $baseQuery)->count(),
            'with_permissions' => (clone $baseQuery)->has('permissions')->count(),
        ];
    }
}
