<?php

declare(strict_types=1);

namespace ApiModel\Service;

use ApiModel\Domain\Repository\PlatformAuditRepositoryInterface;
use ApiModel\Domain\Repository\UserRepositoryInterface;
use ApiModel\Infrastructure\Persistence\Database;
use ApiModel\Shared\Exceptions\BadRequestException;
use ApiModel\Shared\Exceptions\ConflictException;
use ApiModel\Shared\Exceptions\NotFoundException;

final class PlatformService
{
    public function __construct(
        private readonly UserRepositoryInterface $users,
        private readonly PlatformAuditRepositoryInterface $platformAudit,
    ) {}

    public function listUsers(int $page, int $limit, ?string $q): array
    {
        $off = ($page - 1) * $limit;
        $total = $this->users->countUsersForAdmin($q);
        $data = $this->users->listUsersForAdmin($limit, $off, $q);

        return ['data' => $data, 'total' => $total, 'page' => $page, 'limit' => $limit];
    }

    public function createUser(array $jwt, array $dto): array
    {
        $email = strtolower(trim((string) ($dto['email'] ?? '')));
        $name = trim((string) ($dto['name'] ?? ''));
        $password = (string) ($dto['password'] ?? '');
        $role = (string) ($dto['role'] ?? '');
        if ($email === '' || $name === '' || strlen($password) < 8 || $role === '') {
            throw new BadRequestException('Datos inválidos');
        }
        if ($this->users->emailExists($email)) {
            throw new ConflictException('El correo ya está registrado');
        }
        $id = Database::uuid();
        $hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 10]);
        $this->users->insertUserWithPassword($id, $name, $email, $hash, $role, 'es');
        $this->auditLog('USER_CREATED', $jwt['userId'], $id, json_encode(['email' => $email, 'role' => $role]));

        return ['id' => $id, 'name' => $name, 'email' => $email, 'role' => $role, 'is_active' => true];
    }

    public function updateUser(array $jwt, string $id, array $dto): array
    {
        $user = $this->users->findFullById($id);
        if (! $user) {
            throw new NotFoundException();
        }
        if (array_key_exists('name', $dto)) {
            $this->users->updateUserName($id, trim((string) $dto['name']));
        }
        if (array_key_exists('role', $dto)) {
            $this->users->updateUserRole($id, (string) $dto['role']);
        }
        if (array_key_exists('is_active', $dto)) {
            $this->users->updateUserIsActive($id, (bool) $dto['is_active']);
        }
        $user = $this->users->findFullById($id);
        if (! is_array($user)) {
            throw new NotFoundException();
        }
        $this->auditLog('USER_UPDATED', $jwt['userId'], $id, json_encode($dto));

        return ['id' => $user['id'], 'name' => $user['name'], 'email' => $user['email'], 'role' => $user['role'], 'is_active' => (bool) $user['is_active']];
    }

    public function listPlatformAudit(int $page, int $limit): array
    {
        $total = $this->platformAudit->countAll();
        $data = $this->platformAudit->listPage($limit, ($page - 1) * $limit);

        return ['data' => $data, 'total' => $total, 'page' => $page, 'limit' => $limit];
    }

    private function auditLog(string $action, ?string $actor, ?string $target, string $meta): void
    {
        $this->platformAudit->log($action, $actor, $target, $meta);
    }
}
