<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\FormBuilder;

use App\Framework\LiveComponents\Attributes\LiveComponent;
use App\Framework\LiveComponents\Contracts\LiveComponentContract;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
use App\Framework\LiveComponents\ValueObjects\ComponentRenderData;

/**
 * Generische Multi-Step Form Component
 *
 * Nutzt bestehenden FormBuilder + FormDefinition Value Objects
 * für maximale Wiederverwendbarkeit ohne Code-Duplizierung
 */
#[LiveComponent('multi-step-form')]
final readonly class MultiStepFormComponent implements LiveComponentContract
{
    public function __construct(
        public ComponentId $id,
        public MultiStepFormState $state,
        private MultiStepFormDefinition $formDefinition
    ) {}

    public function getRenderData(): ComponentRenderData
    {
        $stepDef = $this->formDefinition->getStep($this->state->currentStep);

        // Build form für aktuellen Step
        $formHtml = $this->buildStepForm($stepDef);

        return new ComponentRenderData(
            templatePath: 'livecomponent-multi-step-form',
            data: [
                'current_step' => $this->state->currentStep,
                'total_steps' => $this->formDefinition->getTotalSteps(),
                'step_title' => $stepDef->title,
                'step_description' => $stepDef->description,
                'form_html' => $formHtml,
                'errors' => $this->state->errors,
                'submitted' => $this->state->submitted,
                'submission_id' => $this->state->submissionId,
                'can_go_previous' => $this->state->currentStep > 1,
                'can_go_next' => $this->state->currentStep < $this->formDefinition->getTotalSteps(),
                'is_last_step' => $this->state->currentStep === $this->formDefinition->getTotalSteps(),
                'progress_percentage' => (int) round(($this->state->currentStep / $this->formDefinition->getTotalSteps()) * 100),
                'form_data_json' => json_encode($this->state->formData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE),
            ]
        );
    }

    // Actions

    public function updateField(array $params = []): MultiStepFormState
    {
        $newState = $this->state;

        // Update form data with changed fields
        foreach ($params as $field => $value) {
            $newState = $newState->withFieldUpdate($field, $value);
        }

        // Clear errors on update
        return $newState->withErrors([]);
    }

    public function nextStep(array $params = []): MultiStepFormState
    {
        // Update form data
        $newState = $this->state;
        foreach ($params as $field => $value) {
            $newState = $newState->withFieldUpdate($field, $value);
        }

        // Validate current step
        $stepDef = $this->formDefinition->getStep($newState->currentStep);
        $errors = $stepDef->validator?->validate($newState->formData) ?? [];

        if (! empty($errors)) {
            return $newState->withErrors($errors);
        }

        // Move to next step
        return $newState->withNextStep();
    }

    public function previousStep(array $params = []): MultiStepFormState
    {
        // Update form data (preserve changes)
        $newState = $this->state;
        foreach ($params as $field => $value) {
            $newState = $newState->withFieldUpdate($field, $value);
        }

        // Move to previous step
        return $newState->withPreviousStep();
    }

    public function submit(array $params = []): MultiStepFormState
    {
        // Update form data
        $newState = $this->state;
        foreach ($params as $field => $value) {
            $newState = $newState->withFieldUpdate($field, $value);
        }

        // Validate all steps
        $allErrors = [];
        foreach ($this->formDefinition->steps as $stepDef) {
            $stepErrors = $stepDef->validator?->validate($newState->formData) ?? [];
            $allErrors = array_merge($allErrors, $stepErrors);
        }

        if (! empty($allErrors)) {
            return $newState->withErrors($allErrors);
        }

        // Handle submission
        $submitHandler = $this->formDefinition->submitHandler;
        $submissionId = 'FORM-' . strtoupper(substr(md5((string) time()), 0, 8));

        if ($submitHandler) {
            $result = $submitHandler->handle($newState->formData);
            // TODO: Handle redirect in result
        }

        return $newState->withSubmitted($submissionId);
    }

    public function reset(): MultiStepFormState
    {
        return $this->state->withReset();
    }

    // Private Methods

    private function buildStepForm(FormStepDefinition $stepDef): string
    {
        $builder = LiveFormBuilder::create();

        foreach ($stepDef->fields as $fieldDef) {
            // Check conditional rendering
            if (! $fieldDef->shouldShow($this->state->formData)) {
                continue;
            }

            $value = $this->state->formData[$fieldDef->name] ?? $fieldDef->defaultValue ?? '';

            $builder = match ($fieldDef->type) {
                FieldType::TEXT => $builder->addLiveTextInput(
                    name: $fieldDef->name,
                    value: (string) $value,
                    label: $fieldDef->label,
                    debounceMs: $fieldDef->debounceMs
                ),
                FieldType::EMAIL => $builder->addLiveEmailInput(
                    name: $fieldDef->name,
                    value: (string) $value,
                    label: $fieldDef->label,
                    debounceMs: $fieldDef->debounceMs
                ),
                FieldType::RADIO => $builder->addLiveRadioGroup(
                    name: $fieldDef->name,
                    options: $fieldDef->options ?? [],
                    selectedValue: (string) $value,
                    label: $fieldDef->label
                ),
                FieldType::CHECKBOX => $builder->addLiveCheckbox(
                    name: $fieldDef->name,
                    checked: $value === 'yes' || $value === true,
                    label: $fieldDef->label
                ),
                FieldType::SELECT => $builder->addLiveSelect(
                    name: $fieldDef->name,
                    options: $fieldDef->options ?? [],
                    selectedValue: (string) $value,
                    label: $fieldDef->label
                ),
                default => $builder
            };
        }

        return $builder->build();
    }
}
