<?php

declare(strict_types=1);

namespace App\Application\LiveComponents\TodoList;

use App\Application\LiveComponents\LiveComponentState;

/**
 * TodoListState - Immutable state for TodoList parent component
 *
 * Demonstrates Value Object pattern for component state:
 * - Readonly and immutable
 * - Transformation methods return new instances
 * - Serializable to/from ComponentData
 */
final readonly class TodoListState implements LiveComponentState
{
    public function __construct(
        public array $todos = [],
        public string $filter = 'all' // all, active, completed
    ) {
    }

    /**
     * Create state from ComponentData (deserialization)
     */
    public static function fromArray(array $data): self
    {
        

        return new self(
            todos: $data['todos'] ?? [],
            filter: $data['filter'] ?? 'all'
        );
    }

    /**
     * Convert state to ComponentData (serialization)
     */
    public function toArray(): array
    {
        return [
            'todos' => $this->todos,
            'filter' => $this->filter,
        ];
    }

    /**
     * Add a new todo to the list
     */
    public function withTodoAdded(array $todo): self
    {
        return new self(
            todos: [...$this->todos, $todo],
            filter: $this->filter
        );
    }

    /**
     * Remove a todo by ID
     */
    public function withTodoRemoved(string $todoId): self
    {
        $newTodos = array_filter(
            $this->todos,
            fn ($todo) => $todo['id'] !== $todoId
        );

        return new self(
            todos: array_values($newTodos), // Re-index array
            filter: $this->filter
        );
    }

    /**
     * Update a todo's properties
     */
    public function withTodoUpdated(string $todoId, array $updates): self
    {
        $newTodos = array_map(function ($todo) use ($todoId, $updates) {
            if ($todo['id'] === $todoId) {
                return array_merge($todo, $updates);
            }

            return $todo;
        }, $this->todos);

        return new self(
            todos: $newTodos,
            filter: $this->filter
        );
    }

    /**
     * Toggle a todo's completed status
     */
    public function withTodoToggled(string $todoId): self
    {
        $newTodos = array_map(function ($todo) use ($todoId) {
            if ($todo['id'] === $todoId) {
                $todo['completed'] = ! $todo['completed'];
            }

            return $todo;
        }, $this->todos);

        return new self(
            todos: $newTodos,
            filter: $this->filter
        );
    }

    /**
     * Clear all completed todos
     */
    public function withCompletedCleared(): self
    {
        $newTodos = array_filter(
            $this->todos,
            fn ($todo) => ! $todo['completed']
        );

        return new self(
            todos: array_values($newTodos), // Re-index array
            filter: $this->filter
        );
    }

    /**
     * Set the filter (all, active, completed)
     */
    public function withFilter(string $filter): self
    {
        if (! in_array($filter, ['all', 'active', 'completed'], true)) {
            throw new \InvalidArgumentException("Invalid filter: {$filter}");
        }

        return new self(
            todos: $this->todos,
            filter: $filter
        );
    }

    /**
     * Toggle all todos to the same completed state
     */
    public function withAllToggled(bool $completed): self
    {
        $newTodos = array_map(function ($todo) use ($completed) {
            $todo['completed'] = $completed;

            return $todo;
        }, $this->todos);

        return new self(
            todos: $newTodos,
            filter: $this->filter
        );
    }

    /**
     * Get filtered todos based on current filter
     */
    public function getFilteredTodos(): array
    {
        return match ($this->filter) {
            'active' => array_filter($this->todos, fn ($todo) => ! $todo['completed']),
            'completed' => array_filter($this->todos, fn ($todo) => $todo['completed']),
            default => $this->todos
        };
    }

    /**
     * Get statistics about the todos
     */
    public function getStats(): array
    {
        $totalCount = count($this->todos);
        $activeCount = count(array_filter($this->todos, fn ($todo) => ! $todo['completed']));
        $completedCount = $totalCount - $activeCount;

        return [
            'total_count' => $totalCount,
            'active_count' => $activeCount,
            'completed_count' => $completedCount,
            'has_todos' => $totalCount > 0,
            'show_clear_completed' => $completedCount > 0,
        ];
    }
}
