<?php

declare(strict_types=1);

namespace ApiModel\Service;

use ApiModel\Domain\Repository\UserRepositoryInterface;

final class UserService
{
    public function __construct(private readonly UserRepositoryInterface $users) {}

    public function me(string $userId): array
    {
        return $this->users->findProfileById($userId);
    }

    public function updateMyLanguage(string $userId, string $language): array
    {
        return $this->users->updateLanguage($userId, $language);
    }

    public function updateMyPhoto(string $userId, ?string $photo): array
    {
        if ($photo === null || trim($photo) === '') {
            $this->users->updatePhoto($userId, null);

            return ['photo' => null];
        }

        if (! preg_match('#^data:image/(jpeg|jpg|png|webp|gif);base64,#i', $photo)) {
            throw new \ApiModel\Shared\Exceptions\BadRequestException('Formato de imagen inválido. Use JPEG, PNG, WEBP o GIF.');
        }

        $commaPos = strpos($photo, ',');
        if ($commaPos === false) {
            throw new \ApiModel\Shared\Exceptions\BadRequestException('Imagen inválida');
        }

        $binary = base64_decode(substr($photo, $commaPos + 1), true);
        if ($binary === false) {
            throw new \ApiModel\Shared\Exceptions\BadRequestException('Imagen inválida');
        }

        if (strlen($binary) > 512000) {
            throw new \ApiModel\Shared\Exceptions\BadRequestException('La imagen no debe superar 500 KB');
        }

        $this->users->updatePhoto($userId, $photo);

        return ['photo' => $photo];
    }

    /** @return list<array<string, mixed>> */
    public function listUsersForAdmin(?string $search): array
    {
        return $this->users->listUsersForAdmin(100, 0, $search);
    }

    /** @param list<string> $roleIds */
    public function createUser(string $name, string $email, array $roleIds, string $language = 'es'): array
    {
        if ($this->users->emailExists($email)) {
            throw new \ApiModel\Shared\Exceptions\BadRequestException('El correo ya está registrado');
        }
        $id = \ApiModel\Infrastructure\Persistence\Database::uuid();

        $this->users->insertUserWithoutPassword($id, $name, $email, $language);
        $this->users->updateUserRoles($id, $roleIds);

        return $this->users->findFullById($id) ?? [];
    }

    /** @param list<string> $roleIds */
    public function updateUser(string $id, string $name, string $email, ?string $password, array $roleIds, bool $isActive): array
    {
        $existing = $this->users->findFullById($id);
        if (!$existing) {
            throw new \ApiModel\Shared\Exceptions\NotFoundException('Usuario no encontrado');
        }

        if (strtolower($existing['email']) !== strtolower($email) && $this->users->emailExists($email)) {
            throw new \ApiModel\Shared\Exceptions\BadRequestException('El correo ya está registrado');
        }

        $this->users->updateUserName($id, $name);
        if (strtolower($existing['email']) !== strtolower($email)) {
            $this->users->updateUserEmail($id, $email);
        }
        $this->users->updateUserIsActive($id, $isActive);
        $this->users->updateUserRoles($id, $roleIds);

        if ($password !== null && trim($password) !== '') {
            $passwordHash = password_hash($password, PASSWORD_BCRYPT);
            $this->users->updatePasswordHash($id, $passwordHash);
        }

        return $this->users->findFullById($id) ?? [];
    }

    public function deleteUser(string $id): void
    {
        $this->users->deleteUser($id);
    }
}
