<?php

declare(strict_types=1);

namespace App\Service\Admin;

use App\Config\ModelGenerationDefaultsConfig;
use App\Entity\ModelGenerationConfig;
use App\Knowledge\Retrieval\NdjsonHybridRetriever;
use App\Repository\ModelGenerationConfigRepository;
use App\Service\ModelGenerationConfigManager;
use Doctrine\ORM\EntityManagerInterface;

final class ModelGenerationConfigAdminService
{
    public function __construct(
        private readonly ModelGenerationConfigRepository $repository,
        private readonly EntityManagerInterface $em,
        private readonly ModelGenerationConfigManager $manager,
        private readonly NdjsonHybridRetriever $retriever,
        private readonly ModelGenerationDefaultsConfig $defaults,
    ) {}

    public function list(): array
    {
        return $this->repository->findBy(
            [],
            ['active' => 'DESC', 'modelName' => 'ASC', 'version' => 'DESC']
        );
    }

    public function create(array $data): ModelGenerationConfig
    {
        $modelName = $this->requireString($data['model_name'] ?? null, 'model_name');

        $version = $this->repository->findNextVersion($modelName);

        $config = new ModelGenerationConfig(
            modelName: $modelName,
            version: $version,
            stream: (bool)($data['stream'] ?? $this->defaults->isStream()),
            temperature: (float)($data['temperature'] ?? $this->defaults->getTemperature()),
            topK: (int)($data['top_k'] ?? $this->defaults->getTopK()),
            topP: (float)($data['top_p'] ?? $this->defaults->getTopP()),
            repeatPenalty: (float)($data['repeat_penalty'] ?? $this->defaults->getRepeatPenalty()),
            numCtx: (int)($data['num_ctx'] ?? $this->defaults->getNumCtx()),
            active: false,
            retrievalMaxChunks: (int)($data['retrieval_max_chunks'] ?? $this->defaults->getRetrievalMaxChunks()),
            retrievalVectorTopK: (int)($data['retrieval_vector_top_k'] ?? $this->defaults->getRetrievalVectorTopK()),
        );

        $this->em->persist($config);
        $this->em->flush();

        return $config;
    }

    public function activate(ModelGenerationConfig $config): void
    {
        $this->manager->activate($config);
    }

    public function delete(ModelGenerationConfig $config): void
    {
        if ($config->isActive()) {
            throw new \RuntimeException('Aktive Konfiguration kann nicht geloescht werden.');
        }

        $this->em->remove($config);
        $this->em->flush();
    }

    public function testRetrieval(ModelGenerationConfig $config, string $prompt): array
    {
        if (trim($prompt) === '') {
            return [];
        }

        return $this->retriever->retrieveDebug($prompt, $config);
    }

    private function requireString(mixed $value, string $field): string
    {
        if (!is_string($value) || trim($value) === '') {
            throw new \InvalidArgumentException("Invalid value for {$field}");
        }
        return trim($value);
    }
}
