<?php

declare(strict_types=1);

namespace App\Application\LiveComponents\DynamicForm;

use App\Application\LiveComponents\LiveComponentState;

/**
 * Type-safe state for DynamicFormComponent
 *
 * Provides compile-time type safety for multi-step dynamic forms.
 * All properties are readonly and immutable - transformations return new instances.
 */
final readonly class DynamicFormState implements LiveComponentState
{
    public function __construct(
        public int $currentStep = 1,
        public int $totalSteps = 4,
        public array $formData = [],
        public array $errors = [],
        public bool $submitted = false,
        public ?string $submissionId = null
    ) {
    }

    /**
     * Create from array (LiveComponentState interface)
     */
    public static function fromArray(array $data): self
    {
        return new self(
            currentStep: (int) ($data['current_step'] ?? 1),
            totalSteps: (int) ($data['total_steps'] ?? 4),
            formData: $data['form_data'] ?? [],
            errors: $data['errors'] ?? [],
            submitted: (bool) ($data['submitted'] ?? false),
            submissionId: $data['submission_id'] ?? null
        );
    }

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

    /**
     * Convert to array (LiveComponentState interface)
     */
    public function toArray(): array
    {
        return [
            'current_step' => $this->currentStep,
            'total_steps' => $this->totalSteps,
            'form_data' => $this->formData,
            'errors' => $this->errors,
            'submitted' => $this->submitted,
            'submission_id' => $this->submissionId,
        ];
    }

    /**
     * Move to next step
     */
    public function withNextStep(array $errors = []): self
    {
        if (! empty($errors)) {
            return new self(
                currentStep: $this->currentStep,
                totalSteps: $this->totalSteps,
                formData: $this->formData,
                errors: $errors,
                submitted: $this->submitted,
                submissionId: $this->submissionId
            );
        }

        return new self(
            currentStep: min($this->currentStep + 1, $this->totalSteps),
            totalSteps: $this->totalSteps,
            formData: $this->formData,
            errors: [],
            submitted: $this->submitted,
            submissionId: $this->submissionId
        );
    }

    /**
     * Move to previous step
     */
    public function withPreviousStep(): self
    {
        return new self(
            currentStep: max($this->currentStep - 1, 1),
            totalSteps: $this->totalSteps,
            formData: $this->formData,
            errors: [],
            submitted: $this->submitted,
            submissionId: $this->submissionId
        );
    }

    /**
     * Update a form field
     */
    public function withUpdatedField(string $field, string $value): self
    {
        $formData = $this->formData;
        $formData[$field] = $value;

        return new self(
            currentStep: $this->currentStep,
            totalSteps: $this->totalSteps,
            formData: $formData,
            errors: [],
            submitted: $this->submitted,
            submissionId: $this->submissionId
        );
    }

    /**
     * Update multiple form fields at once
     */
    public function withUpdatedFields(array $fields): self
    {
        $formData = array_merge($this->formData, $fields);

        return new self(
            currentStep: $this->currentStep,
            totalSteps: $this->totalSteps,
            formData: $formData,
            errors: [],
            submitted: $this->submitted,
            submissionId: $this->submissionId
        );
    }

    /**
     * Submit the form
     */
    public function withSubmission(array $errors, ?string $submissionId = null): self
    {
        if (! empty($errors)) {
            return new self(
                currentStep: $this->totalSteps,
                totalSteps: $this->totalSteps,
                formData: $this->formData,
                errors: $errors,
                submitted: false,
                submissionId: null
            );
        }

        return new self(
            currentStep: $this->totalSteps,
            totalSteps: $this->totalSteps,
            formData: $this->formData,
            errors: [],
            submitted: true,
            submissionId: $submissionId
        );
    }

    /**
     * Reset the form
     */
    public function withReset(): self
    {
        return new self();
    }

    /**
     * Check if can go to next step
     */
    public function canGoNext(): bool
    {
        return $this->currentStep < $this->totalSteps;
    }

    /**
     * Check if can go to previous step
     */
    public function canGoPrevious(): bool
    {
        return $this->currentStep > 1;
    }

    /**
     * Check if is first step
     */
    public function isFirstStep(): bool
    {
        return $this->currentStep === 1;
    }

    /**
     * Check if is last step
     */
    public function isLastStep(): bool
    {
        return $this->currentStep === $this->totalSteps;
    }

    /**
     * Check if has errors
     */
    public function hasErrors(): bool
    {
        return ! empty($this->errors);
    }

    /**
     * Get error count
     */
    public function getErrorCount(): int
    {
        return count($this->errors);
    }

    /**
     * Get progress percentage
     */
    public function getProgressPercentage(): int
    {
        return (int) round(($this->currentStep / $this->totalSteps) * 100);
    }

    /**
     * Get progress text
     */
    public function getProgressText(): string
    {
        return "Schritt {$this->currentStep} von {$this->totalSteps}";
    }

    /**
     * Get submit button text
     */
    public function getSubmitButtonText(): string
    {
        return $this->submitted ? 'Gesendet' : 'Absenden';
    }

    /**
     * Get next button text
     */
    public function getNextButtonText(): string
    {
        return $this->currentStep === $this->totalSteps - 1 ? 'Zur Übersicht' : 'Weiter';
    }

    /**
     * Check if should show business fields
     */
    public function shouldShowBusinessFields(): bool
    {
        return ($this->formData['account_type'] ?? '') === 'business';
    }

    /**
     * Get step title
     */
    public function getStepTitle(int $step): string
    {
        return match($step) {
            1 => 'Persönliche Informationen',
            2 => 'Konto-Typ',
            3 => 'Präferenzen',
            4 => 'Übersicht & Bestätigung',
            default => 'Schritt ' . $step
        };
    }

    /**
     * Get step description
     */
    public function getStepDescription(int $step): string
    {
        return match($step) {
            1 => 'Bitte geben Sie Ihre persönlichen Daten ein',
            2 => 'Wählen Sie Ihren Konto-Typ',
            3 => 'Passen Sie Ihre Einstellungen an',
            4 => 'Überprüfen Sie Ihre Angaben',
            default => ''
        };
    }

    /**
     * Get steps for display
     */
    public function getStepsForDisplay(): array
    {
        $steps = [];

        for ($i = 1; $i <= $this->totalSteps; $i++) {
            $steps[] = [
                'number' => $i,
                'title' => $this->getStepTitle($i),
                'isActive' => $i === $this->currentStep,
                'isCompleted' => $i < $this->currentStep,
                'isPending' => $i > $this->currentStep,
                'stepClass' => $this->getStepClass($i),
            ];
        }

        return $steps;
    }

    /**
     * Get step CSS class
     */
    private function getStepClass(int $stepNumber): string
    {
        if ($stepNumber === $this->currentStep) {
            return 'step-active';
        }

        if ($stepNumber < $this->currentStep) {
            return 'step-completed';
        }

        return 'step-pending';
    }
}
