<?php
namespace App\Controllers;

use App\Services\AuthService;
use App\Services\OpenAiService;
use App\Services\RbacService;
use App\Utils\Sanitizer;

class RbacController extends ApiController
{
    private RbacService $rbacService;
    private AuthService $authService;
    private ?OpenAiService $openAiService;

    public function __construct(RbacService $rbacService, AuthService $authService, ?OpenAiService $openAiService = null)
    {
        $this->rbacService = $rbacService;
        $this->authService = $authService;
        $this->openAiService = $openAiService;
    }

    private function requireAdmin(): void
    {
        if (!$this->authService->isAdmin() && !$this->hasDelegatedCapability('rbac.admin.manage')) {
            $this->errorResponse('فقط ادمین مجاز است', 403);
        }
    }

    public function getCatalog(): void
    {
        $this->requireAdmin();
        $this->successResponse($this->rbacService->getCatalog());
    }

    public function getRolePermissions(): void
    {
        $this->requireAdmin();
        $roleKey = Sanitizer::sanitize($_REQUEST['role_key'] ?? '');
        if ($roleKey === '') {
            $this->errorResponse('role_key الزامی است');
        }
        $this->successResponse($this->rbacService->getRolePermissions($roleKey));
    }

    public function getCurrentPermissions(): void
    {
        if (!$this->authService->isAuthenticated()) {
            $this->errorResponse('Unauthenticated', 401);
        }
        $roleKey = (string)($_SESSION['role'] ?? 'agent');
        $payload = $this->rbacService->getCurrentPermissions((int)($_SESSION['user_id'] ?? 0), $roleKey);
        if ($this->openAiService !== null) {
            $payload['ai_feature_enabled'] = $this->openAiService->isEnabled() ? '1' : '0';
        }
        if ($this->openAiService !== null && !$this->openAiService->isEnabled()) {
            $payload['capabilities'] = array_values(array_filter((array)($payload['capabilities'] ?? []), static function ($key) {
                return strpos((string)$key, 'ai.') !== 0 && (string)$key !== 'menu.ai_assistant';
            }));
        }
        $this->successResponse($payload);
    }

    public function getUserPermissions(): void
    {
        $this->requireAdmin();
        $userId = (int)($_REQUEST['user_id'] ?? 0);
        if ($userId <= 0) {
            $this->errorResponse('user_id الزامی است');
        }
        $this->successResponse($this->rbacService->getUserPermissions($userId));
    }

    public function saveRole(): void
    {
        $this->requireAdmin();
        $id = (int)($_POST['id'] ?? 0);
        $roleKey = Sanitizer::sanitize($_POST['role_key'] ?? '');
        $title = Sanitizer::sanitize($_POST['title'] ?? '');
        $isActive = isset($_POST['is_active']) ? (int)$_POST['is_active'] : 1;
        $templateFrom = Sanitizer::sanitize($_POST['template_from_role_key'] ?? '');
        $metaJson = $_POST['meta_json'] ?? null;

        try {
            $saved = $this->rbacService->saveRole([
                'id' => $id,
                'role_key' => $roleKey,
                'title' => $title,
                'is_active' => $isActive,
                'template_from_role_key' => $templateFrom,
                'meta_json' => $metaJson,
            ]);
            $this->successResponse(['role' => $saved], 'نقش ذخیره شد');
        } catch (\InvalidArgumentException $e) {
            $this->errorResponse($e->getMessage(), 422);
        } catch (\Throwable $e) {
            $this->errorResponse($e->getMessage(), 400);
        }
    }

    public function cloneRole(): void
    {
        $this->requireAdmin();
        $newRoleKey = Sanitizer::sanitize($_POST['new_role_key'] ?? '');
        $newTitle = Sanitizer::sanitize($_POST['new_title'] ?? '');
        $templateRoleKey = Sanitizer::sanitize($_POST['template_role_key'] ?? '');

        try {
            $saved = $this->rbacService->cloneRoleFromTemplate($newRoleKey, $newTitle, $templateRoleKey);
            $this->successResponse(['role' => $saved], 'نقش از تمپلیت ایجاد شد');
        } catch (\InvalidArgumentException $e) {
            $this->errorResponse($e->getMessage(), 422);
        } catch (\Throwable $e) {
            $this->errorResponse($e->getMessage(), 400);
        }
    }

    public function deleteRole(): void
    {
        $this->requireAdmin();
        $roleKey = Sanitizer::sanitize($_POST['role_key'] ?? '');
        if ($roleKey === '') {
            $this->errorResponse('role_key الزامی است');
        }
        try {
            $this->rbacService->deleteRole($roleKey);
            $this->successResponse([], 'نقش حذف شد');
        } catch (\InvalidArgumentException $e) {
            $this->errorResponse($e->getMessage(), 422);
        } catch (\Throwable $e) {
            $this->errorResponse($e->getMessage(), 400);
        }
    }

    public function saveRoleCapabilities(): void
    {
        $this->requireAdmin();
        $roleKey = Sanitizer::sanitize($_POST['role_key'] ?? '');
        if ($roleKey === '') {
            $this->errorResponse('role_key الزامی است');
        }
        try {
            $raw = $this->decodeArrayInput($_POST['capability_keys'] ?? [], 'capability_keys', true);
            $this->rbacService->saveRoleCapabilities($roleKey, (array)$raw);
            $this->successResponse([], 'دسترسی‌های نقش ذخیره شد');
        } catch (\InvalidArgumentException $e) {
            $this->errorResponse($e->getMessage(), 422);
        } catch (\Throwable $e) {
            $this->errorResponse($e->getMessage(), 400);
        }
    }

    public function saveRoleScopes(): void
    {
        $this->requireAdmin();
        $roleKey = Sanitizer::sanitize($_POST['role_key'] ?? '');
        if ($roleKey === '') {
            $this->errorResponse('role_key الزامی است');
        }
        try {
            $scopes = $this->decodeArrayInput($_POST['scopes'] ?? '[]', 'scopes', false);
            $this->rbacService->saveRoleDataScopes($roleKey, $scopes);
            $this->successResponse([], 'محدوده‌های داده نقش ذخیره شد');
        } catch (\InvalidArgumentException $e) {
            $this->errorResponse($e->getMessage(), 422);
        } catch (\Throwable $e) {
            $this->errorResponse($e->getMessage(), 400);
        }
    }

    public function saveUserCapabilities(): void
    {
        $this->requireAdmin();
        $userId = (int)($_POST['user_id'] ?? 0);
        if ($userId <= 0) {
            $this->errorResponse('user_id الزامی است');
        }
        try {
            $allow = $this->decodeArrayInput($_POST['allow_keys'] ?? [], 'allow_keys', true);
            $deny = $this->decodeArrayInput($_POST['deny_keys'] ?? [], 'deny_keys', true);
            $this->rbacService->saveUserCapabilityOverrides($userId, $allow, $deny);
            $this->successResponse([], 'دسترسی‌های اختصاصی کاربر ذخیره شد');
        } catch (\InvalidArgumentException $e) {
            $this->errorResponse($e->getMessage(), 422);
        } catch (\Throwable $e) {
            $this->errorResponse($e->getMessage(), 400);
        }
    }

    public function saveUserScopes(): void
    {
        $this->requireAdmin();
        $userId = (int)($_POST['user_id'] ?? 0);
        if ($userId <= 0) {
            $this->errorResponse('user_id الزامی است');
        }
        try {
            $scopes = $this->decodeArrayInput($_POST['scopes'] ?? '[]', 'scopes', false);
            $this->rbacService->saveUserDataScopes($userId, $scopes);
            $this->successResponse([], 'محدوده‌های اختصاصی کاربر ذخیره شد');
        } catch (\InvalidArgumentException $e) {
            $this->errorResponse($e->getMessage(), 422);
        } catch (\Throwable $e) {
            $this->errorResponse($e->getMessage(), 400);
        }
    }

    private function decodeArrayInput($raw, string $field, bool $allowCsv): array
    {
        if (is_array($raw)) {
            return $raw;
        }

        $text = trim((string)$raw);
        if ($text === '') {
            return [];
        }

        $decoded = json_decode($text, true);
        if (json_last_error() === JSON_ERROR_NONE) {
            if (!is_array($decoded)) {
                throw new \InvalidArgumentException($field . ' باید آرایه باشد');
            }
            return $decoded;
        }

        if ($allowCsv && strpos($text, ',') !== false) {
            return array_filter(array_map('trim', explode(',', $text)));
        }

        throw new \InvalidArgumentException($field . ' JSON نامعتبر است: ' . json_last_error_msg());
    }
}
