<?php

declare(strict_types=1);

namespace App\Application\LiveComponents\Autocomplete;

use App\Application\LiveComponents\LiveComponentState;

/**
 * Type-safe state for AutocompleteComponent
 *
 * Provides compile-time type safety for autocomplete functionality.
 * All properties are readonly and immutable - transformations return new instances.
 */
final readonly class AutocompleteState implements LiveComponentState
{
    public function __construct(
        public string $query = '',
        public array $suggestions = [],
        public string $context = 'general',
        public bool $showDropdown = false,
        public array $recentSearches = [],
        public ?string $selectedValue = null,
        public int $selectedIndex = -1,
        public string $dataSource = 'demo'
    ) {
    }

    /**
     * Create from ComponentData (Framework → Domain conversion)
     */
    public static function fromArray(array $data): self
    {
        return new self(
            query: (string) ($data['query'] ?? ''),
            suggestions: ($data['suggestions'] ?? []),
            context: (string) ($data['context'] ?? 'general'),
            showDropdown: (bool) ($data['show_dropdown'] ?? false),
            recentSearches: ($data['recent_searches'] ?? []),
            selectedValue: $data['selected_value'],
            selectedIndex: (int) ($data['selected_index'] ?? -1),
            dataSource: (string) ($data['data_source'] ?? 'demo')
        );
    }

    /**
     * Create empty state with defaults
     */
    public static function empty(): self
    {
        return new self();
    }

    /**
     * Convert to ComponentData (Domain → Framework conversion)
     */
    public function toArray(): array
    {
        return [
            'query' => $this->query,
            'suggestions' => $this->suggestions,
            'context' => $this->context,
            'show_dropdown' => $this->showDropdown,
            'recent_searches' => $this->recentSearches,
            'selected_value' => $this->selectedValue,
            'selected_index' => $this->selectedIndex,
            'data_source' => $this->dataSource,
        ];
    }

    /**
     * Update with new suggestions
     */
    public function withSuggestions(string $query, array $suggestions): self
    {
        return new self(
            query: $query,
            suggestions: $suggestions,
            context: $this->context,
            showDropdown: ! empty($suggestions),
            recentSearches: $this->recentSearches,
            selectedValue: $this->selectedValue,
            selectedIndex: -1,
            dataSource: $this->dataSource
        );
    }

    /**
     * Select a suggestion
     */
    public function withSelectedSuggestion(string $value, int $index): self
    {
        // Add to recent searches if not already present
        $recentSearches = $this->recentSearches;
        if (! in_array($value, $recentSearches, true)) {
            array_unshift($recentSearches, $value);
            $recentSearches = array_slice($recentSearches, 0, 10); // Keep last 10
        }

        return new self(
            query: $value,
            suggestions: [],
            context: $this->context,
            showDropdown: false,
            recentSearches: $recentSearches,
            selectedValue: $value,
            selectedIndex: $index,
            dataSource: $this->dataSource
        );
    }

    /**
     * Clear recent searches
     */
    public function withClearedRecent(): self
    {
        return new self(
            query: $this->query,
            suggestions: $this->suggestions,
            context: $this->context,
            showDropdown: $this->showDropdown,
            recentSearches: [],
            selectedValue: $this->selectedValue,
            selectedIndex: $this->selectedIndex,
            dataSource: $this->dataSource
        );
    }

    /**
     * Change context
     */
    public function withContext(string $context): self
    {
        return new self(
            query: $this->query,
            suggestions: [],
            context: $context,
            showDropdown: false,
            recentSearches: $this->recentSearches,
            selectedValue: $this->selectedValue,
            selectedIndex: -1,
            dataSource: $this->dataSource
        );
    }

    /**
     * Hide dropdown
     */
    public function withHiddenDropdown(): self
    {
        return new self(
            query: $this->query,
            suggestions: $this->suggestions,
            context: $this->context,
            showDropdown: false,
            recentSearches: $this->recentSearches,
            selectedValue: $this->selectedValue,
            selectedIndex: $this->selectedIndex,
            dataSource: $this->dataSource
        );
    }

    /**
     * Reset to empty state
     */
    public function reset(): self
    {
        return new self(
            query: '',
            suggestions: [],
            context: $this->context,
            showDropdown: false,
            recentSearches: $this->recentSearches,
            selectedValue: null,
            selectedIndex: -1,
            dataSource: $this->dataSource
        );
    }

    /**
     * Check if there are suggestions
     */
    public function hasSuggestions(): bool
    {
        return ! empty($this->suggestions);
    }

    /**
     * Check if there are recent searches
     */
    public function hasRecentSearches(): bool
    {
        return ! empty($this->recentSearches);
    }

    /**
     * Get suggestion count
     */
    public function getSuggestionCount(): int
    {
        return count($this->suggestions);
    }

}
