<?php

declare(strict_types=1);

namespace App\Services;

use App\Repositories\RoleRepository;
use InvalidArgumentException;
use PDO;
use RuntimeException;

final class RoleService
{
    public function __construct(
        private PDO $pdo,
        private RoleRepository $roles,
    ) {
    }

    public function create(string $name): int
    {
        $name = trim($name);
        if ($name === '') {
            throw new InvalidArgumentException('اسم الدور مطلوب');
        }
        if ($this->roles->roleNameExists($name)) {
            throw new InvalidArgumentException('اسم الدور مستخدم بالفعل');
        }
        return $this->roles->create($name);
    }

    public function savePermissions(int $roleId, mixed $codes): void
    {
        if ($roleId <= 0) {
            throw new InvalidArgumentException('دور غير صحيح');
        }
        if (!$this->roles->findRole($roleId)) {
            throw new RuntimeException('الدور غير موجود');
        }

        $permissions = $this->normalizePermissionCodes($codes);

        try {
            $this->pdo->beginTransaction();
            $this->roles->replacePermissions($roleId, $permissions);
            $this->pdo->commit();
        } catch (\Throwable $e) {
            if ($this->pdo->inTransaction()) {
                $this->pdo->rollBack();
            }
            throw $e;
        }
    }

    public function delete(int $roleId): void
    {
        if ($roleId <= 0) {
            throw new InvalidArgumentException('دور غير صحيح');
        }
        if ($this->roles->isSystemRole($roleId)) {
            throw new InvalidArgumentException('لا يمكن حذف دور نظام');
        }
        if (!$this->roles->findRole($roleId)) {
            throw new RuntimeException('الدور غير موجود');
        }
        $this->roles->delete($roleId);
    }

    private function normalizePermissionCodes(mixed $codes): array
    {
        if (!is_array($codes)) {
            return [];
        }

        $clean = [];
        foreach ($codes as $code) {
            $value = trim((string)$code);
            if ($value !== '') {
                $clean[$value] = $value;
            }
        }
        return array_values($clean);
    }
}
