<?php

declare(strict_types=1);

namespace App\Application\Search;

use App\Framework\Exception\ErrorCode;
use App\Framework\Exception\FrameworkException;
use App\Framework\Search\SearchFieldConfig;
use App\Framework\Search\SearchFieldType;
use App\Framework\Search\SearchIndexConfig;

/**
 * Request object for creating search indexes
 */
final readonly class CreateIndexRequest
{
    /**
     * @param array<string, array<string, mixed>> $fields
     * @param array<string, mixed> $settings
     */
    public function __construct(
        public string $entityType,
        public array $fields,
        public array $settings = [],
        public bool $enabled = true
    ) {
    }

    /**
     * @param array<string, mixed> $data
     */
    public static function fromArray(string $entityType, array $data): self
    {
        $fields = $data['fields'] ?? [];
        $settings = $data['settings'] ?? [];
        $enabled = $data['enabled'] ?? true;

        // Validate required fields
        if (empty($fields)) {
            throw FrameworkException::create(
                ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                'At least one field configuration is required'
            );
        }

        // Validate field configurations
        foreach ($fields as $fieldName => $fieldConfig) {
            if (! is_array($fieldConfig) || ! isset($fieldConfig['type'])) {
                throw FrameworkException::create(
                    ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                    "Invalid field configuration for '{$fieldName}'. Type is required."
                );
            }

            // Validate field type
            try {
                SearchFieldType::from($fieldConfig['type']);
            } catch (\ValueError) {
                throw FrameworkException::create(
                    ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                    "Invalid field type '{$fieldConfig['type']}' for field '{$fieldName}'"
                );
            }
        }

        return new self(
            entityType: $entityType,
            fields: $fields,
            settings: $settings,
            enabled: $enabled
        );
    }

    public function toIndexConfig(): SearchIndexConfig
    {
        $fieldConfigs = [];

        foreach ($this->fields as $fieldName => $fieldData) {
            $fieldConfigs[$fieldName] = new SearchFieldConfig(
                type: SearchFieldType::from($fieldData['type']),
                isSearchable: $fieldData['searchable'] ?? true,
                isFilterable: $fieldData['filterable'] ?? true,
                isSortable: $fieldData['sortable'] ?? true,
                isHighlightable: $fieldData['highlightable'] ?? true,
                boost: (float) ($fieldData['boost'] ?? 1.0),
                analyzer: $fieldData['analyzer'] ?? null,
                format: $fieldData['format'] ?? null,
                options: $fieldData['options'] ?? []
            );
        }

        return new SearchIndexConfig(
            entityType: $this->entityType,
            fields: $fieldConfigs,
            settings: $this->settings,
            enabled: $this->enabled
        );
    }

    public static function defaultForEntity(string $entityType): self
    {
        return new self(
            entityType: $entityType,
            fields: [
                'title' => [
                    'type' => 'text',
                    'searchable' => true,
                    'highlightable' => true,
                    'boost' => 2.0,
                ],
                'content' => [
                    'type' => 'text',
                    'searchable' => true,
                    'highlightable' => true,
                    'boost' => 1.0,
                ],
                'category' => [
                    'type' => 'keyword',
                    'searchable' => false,
                    'filterable' => true,
                    'sortable' => true,
                    'highlightable' => false,
                ],
                'tags' => [
                    'type' => 'keyword',
                    'searchable' => true,
                    'filterable' => true,
                    'sortable' => false,
                    'highlightable' => false,
                ],
                'created_at' => [
                    'type' => 'datetime',
                    'searchable' => false,
                    'filterable' => true,
                    'sortable' => true,
                    'highlightable' => false,
                ],
                'status' => [
                    'type' => 'keyword',
                    'searchable' => false,
                    'filterable' => true,
                    'sortable' => true,
                    'highlightable' => false,
                ],
            ]
        );
    }

    /**
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'entity_type' => $this->entityType,
            'fields' => $this->fields,
            'settings' => $this->settings,
            'enabled' => $this->enabled,
        ];
    }
}
