<?php

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validation;

final class LLMConfigsValidator
{
    use ValidatesRequests;

    /**
     * @param array $requestData
     * @throws \InvalidArgumentException
     * @return void
     */
    public static function validateCreateUpdateRequest(array $requestData)
    {
        $validator = Validation::createValidator();
        $constraints = new Assert\Collection(fields: [
            'provider' => [
                new Assert\Required([
                    new Assert\Choice(
                        choices: array_column(array: LLMProviderType::cases(), column_key: 'value')
                    ),
                                        new Assert\Callback(callback: function ($provider, $context) {
                                            $data = $context->getRoot();
                                            $token = $data['token'] ?? null;

                                            // Token is required for all providers except 'ollama'
                                            if ($provider !== LLMProviderType::OLLAMA->value && !$token) {
                                                $context->buildViolation('API Token is required for all providers except ' . LLMProviderType::OLLAMA->value)
                                                    ->addViolation();
                                            }
                                        })
                ]),
            ],
            'model' => [
                new Assert\Required(),
                new Assert\Type('string', message: 'Model must be a string'),
                new Assert\Length(
                    min: 1,
                    max: 255
                )
            ],
            'token' => [
                new Assert\Optional([
                    new Assert\Type('string'),
                    new Assert\Length(
                        min: 0,
                        max: 255
                    )
                ])
            ],
            'base_url' => [
                new Assert\Optional([
                    new Assert\Type('string', message: 'Base URL must be a string'),
                    new Assert\Url(message: 'Base URL must be a valid URL'),
                    new Assert\Length(
                        max: 500
                    )
                ])
            ],
            'name' => [
                new Assert\Optional([
                    new Assert\Type('string', message: 'Name must be a string'),
                    new Assert\Length(
                        min: 1,
                        max: 255
                    )
                ])
            ],
            'description' => [
                new Assert\Optional([
                    new Assert\Type('string', message: 'Description must be a string'),
                    new Assert\Length(
                        max: 4012
                    )
                ])
            ],
            'meta' => [
                new Assert\Optional([
                    new Assert\Type('array', message: 'Meta must be an array'),
                    new Assert\All([
                        new Assert\Type(
                            ['string', 'integer', 'float', 'boolean', 'null'],
                            message: 'Meta values must be scalar types or null'
                        )
                    ])
                ])
            ]
        ], allowExtraFields: false);

        self::throwOnIssues($validator->validate($requestData, $constraints));
    }
}
