<?php
declare(strict_types=1);

namespace PpPhp\Core\Designer\Form;

final class DesignerFormDefinition
{
    /** @param array<int, DesignerFormSection> $sections */
    public function __construct(
        private readonly string $formId,
        private readonly string $mode = 'add',
        private readonly string $title = '',
        private readonly DesignerFormLayout $layout = new DesignerFormLayout(),
        private readonly array $sections = [],
        private readonly array $actions = [],
        private readonly array $metadata = []
    ) {}

    public static function create(string $formId, string $mode = 'add', string $title = '', string $layout = 'one_column'): self
    {
        return new self(
            $formId,
            $mode,
            $title !== '' ? $title : ucfirst($mode) . ' Form',
            DesignerFormLayout::fromName($layout),
            [DesignerFormSection::create('general', 'General')],
            self::defaultActions($mode),
            ['version' => '1.0.0']
        );
    }

    public static function fromArray(array $data): self
    {
        $sections = [];
        foreach ((array) ($data['sections'] ?? []) as $section) {
            if (is_array($section)) {
                $sections[] = DesignerFormSection::fromArray($section);
            }
        }

        return new self(
            (string) ($data['formId'] ?? $data['id'] ?? 'form'),
            (string) ($data['mode'] ?? 'add'),
            (string) ($data['title'] ?? 'Form'),
            DesignerFormLayout::fromName((string) ($data['layout']['layout'] ?? $data['layout'] ?? 'one_column')),
            $sections,
            (array) ($data['actions'] ?? []),
            (array) ($data['metadata'] ?? $data['meta'] ?? [])
        );
    }

    public function formId(): string { return $this->formId; }
    public function mode(): string { return $this->mode; }
    public function sections(): array { return $this->sections; }

    public function addField(DesignerFormField $field, string $sectionId = 'general'): self
    {
        $sections = $this->sections;
        $found = false;

        foreach ($sections as $i => $section) {
            if ($section->sectionId() === $sectionId) {
                $sections[$i] = $section->addField($field->withLayout(['span' => $this->layout->fieldSpan()]));
                $found = true;
                break;
            }
        }

        if (!$found) {
            $sections[] = DesignerFormSection::create($sectionId, ucfirst($sectionId), [$field->withLayout(['span' => $this->layout->fieldSpan()])]);
        }

        return new self($this->formId, $this->mode, $this->title, $this->layout, $sections, $this->actions, $this->metadata);
    }

    public function removeField(string $fieldName): self
    {
        return new self(
            $this->formId,
            $this->mode,
            $this->title,
            $this->layout,
            array_map(static fn (DesignerFormSection $section): DesignerFormSection => $section->removeField($fieldName), $this->sections),
            $this->actions,
            $this->metadata
        );
    }

    public function fields(): array
    {
        $fields = [];
        foreach ($this->sections as $section) {
            foreach ($section->fields() as $field) {
                $fields[] = $field;
            }
        }
        return $fields;
    }

    public function toComponent(): array
    {
        return [
            'id' => $this->formId,
            'name' => $this->formId,
            'type' => 'form',
            'label' => $this->title,
            'props' => $this->toArray(),
            'children' => [],
            'events' => ['submit', 'cancel', 'validate'],
            'meta' => ['designerRuntime' => 'form', 'version' => '1.0.0'],
        ];
    }

    public function toArray(): array
    {
        return [
            'formId' => $this->formId,
            'id' => $this->formId,
            'mode' => $this->mode,
            'title' => $this->title,
            'layout' => $this->layout->toArray(),
            'sections' => array_map(static fn (DesignerFormSection $section): array => $section->toArray(), $this->sections),
            'actions' => $this->actions,
            'metadata' => $this->metadata,
            'fieldCount' => count($this->fields()),
        ];
    }

    private static function defaultActions(string $mode): array
    {
        return match ($mode) {
            'view' => [['id' => 'back', 'label' => 'Back', 'type' => 'secondary']],
            'edit' => [['id' => 'save', 'label' => 'Save Changes', 'type' => 'primary'], ['id' => 'cancel', 'label' => 'Cancel', 'type' => 'secondary']],
            default => [['id' => 'save', 'label' => 'Save', 'type' => 'primary'], ['id' => 'cancel', 'label' => 'Cancel', 'type' => 'secondary']],
        };
    }
}
