<?php

namespace Daylight\Core\Modules\PageBuilder\Livewire;

use Illuminate\Support\Collection;
use Illuminate\View\View;
use Livewire\Attributes\Modelable;
use Livewire\Component;

class PageBuilder extends Component
{
    #[Modelable]
    public array $components = [];

    public array $availableComponents = [];

    public string $name = 'components';

    public array $collapsed = [];

    public function mount($components = [], $availableComponents = [], string $name = 'components'): void
    {
        $this->components = $components instanceof Collection ? $components->toArray() : (array) $components;
        $this->availableComponents = $this->normalizeAvailableComponents(
            $availableComponents instanceof Collection ? $availableComponents->toArray() : (array) $availableComponents
        );
        $this->name = $name;

        // Add UIDs to existing components
        $this->components = collect($this->components)->map(function ($component, $index) {
            if (! isset($component['_uid'])) {
                $component['_uid'] = 'comp-' . uniqid() . '-' . $index;
            }

            return $component;
        })->toArray();

        // Normalize component data
        foreach ($this->components as &$component) {
            $component = $this->normalizeComponentData($component);
        }
    }

    protected function normalizeAvailableComponents(array $components): array
    {
        return collect($components)->map(function ($component) {
            // Ensure it's an array
            $component = is_array($component) ? $component : (array) $component;

            // Normalize fields if they exist
            if (isset($component['fields'])) {
                $component['fields'] = $this->normalizeFields($component['fields']);
            }

            return $component;
        })->toArray();
    }

    protected function normalizeFields($fields): array
    {
        if ($fields instanceof Collection) {
            $fields = $fields->toArray();
        }

        if (! is_array($fields)) {
            $fields = (array) $fields;
        }

        return collect($fields)->map(function ($field) {
            return $this->normalizeField($field);
        })->toArray();
    }

    protected function normalizeField($field): array
    {
        // If it's a Field object, use its toArray method
        if ($field instanceof \Daylight\Core\Modules\PageBuilder\Entities\Field) {
            return $field->toArray();
        }

        // Convert object to array
        if (is_object($field) && ! $field instanceof Collection) {
            $field = (array) $field;
        }

        if ($field instanceof Collection) {
            $field = $field->toArray();
        }

        if (! is_array($field)) {
            return [];
        }

        $normalized = [
            'type' => $field['type'] ?? null,
            'name' => $field['name'] ?? null,
            'label' => $field['label'] ?? null,
            'options' => $field['options'] ?? [],
            'items' => [],
        ];

        // Add optional fields
        if (isset($field['relatedType'])) {
            $normalized['relatedType'] = $field['relatedType'];
        }
        if (isset($field['amountOfFiles'])) {
            $normalized['amountOfFiles'] = $field['amountOfFiles'];
        }

        // Recursively normalize nested items (for repeater fields)
        if (isset($field['items']) && ! empty($field['items'])) {
            $normalized['items'] = $this->normalizeFields($field['items']);
        }

        return $normalized;
    }

    public function addComponent(string $type): void
    {
        $definition = collect($this->availableComponents)->firstWhere('type', $type);

        if (! $definition) {
            return;
        }

        $component = [
            '_uid' => 'comp-' . uniqid() . '-' . count($this->components),
            'id' => null,
            'type' => $type,
            'data' => $this->getDefaultFieldData($definition['fields'] ?? []),
        ];

        $this->components[] = $this->normalizeComponentData($component);
    }

    public function deleteComponent(int $index): void
    {
        unset($this->components[$index]);
        $this->components = array_values($this->components);
    }

    public function reorderComponents(array $order): void
    {
        $reordered = [];
        foreach ($order as $uid) {
            $component = collect($this->components)->firstWhere('_uid', $uid);
            if ($component) {
                $reordered[] = $component;
            }
        }
        $this->components = $reordered;

        // Normalize component data after reordering to ensure all fields are properly structured
        foreach ($this->components as &$component) {
            $component = $this->normalizeComponentData($component);
        }
    }

    public function toggleCollapse(string $uid): void
    {
        $this->collapsed[$uid] = ! ($this->collapsed[$uid] ?? false);
    }

    public function addRepeaterRow(int $componentIndex, string $fieldName): void
    {
        $component = $this->components[$componentIndex] ?? null;
        if (! $component) {
            return;
        }

        $definition = collect($this->availableComponents)->firstWhere('type', $component['type']);
        $field = collect($definition['fields'] ?? [])->firstWhere('name', $fieldName);

        if (! $field || $field['type'] !== 'repeater') {
            return;
        }

        $newRow = $this->getDefaultFieldData($field['items'] ?? []);
        $this->components[$componentIndex]['data'][$fieldName][] = $newRow;
    }

    public function deleteRepeaterRow(int $componentIndex, string $fieldName, int $rowIndex): void
    {
        if (isset($this->components[$componentIndex]['data'][$fieldName][$rowIndex])) {
            unset($this->components[$componentIndex]['data'][$fieldName][$rowIndex]);
            $this->components[$componentIndex]['data'][$fieldName] = array_values($this->components[$componentIndex]['data'][$fieldName]);
        }
    }

    protected function getDefaultFieldData(array $fields): array
    {
        $data = [];

        foreach ($fields as $field) {
            $fieldArray = is_array($field) ? $field : (array) $field;

            match ($fieldArray['type'] ?? null) {
                'repeater' => $data[$fieldArray['name']] = [],
                'button' => $data[$fieldArray['name']] = ['url' => null, 'label' => null],
                'media' => $data[$fieldArray['name']] = [],
                // 'wysiwyg' => $data[$fieldArray['name']] = '',
                default => $data[$fieldArray['name']] = null,
            };
        }

        return $data;
    }

    protected function normalizeComponentData(array $component): array
    {
        $definition = collect($this->availableComponents)->firstWhere('type', $component['type']);

        if (! $definition) {
            return $component;
        }

        foreach ($definition['fields'] ?? [] as $field) {
            $fieldArray = is_array($field) ? $field : (array) $field;
            $fieldName = $fieldArray['name'];

            if (! isset($component['data'][$fieldName])) {
                match ($fieldArray['type'] ?? null) {
                    'repeater' => $component['data'][$fieldName] = [],
                    'button' => $component['data'][$fieldName] = ['url' => null, 'label' => null],
                    'media' => $component['data'][$fieldName] = [],
                    default => $component['data'][$fieldName] = null,
                };
            }

            // Ensure button fields are objects
            if ($fieldArray['type'] === 'button' && ! is_array($component['data'][$fieldName])) {
                $component['data'][$fieldName] = ['url' => null, 'label' => null];
            }

            // Ensure media and repeater fields are arrays
            if (in_array($fieldArray['type'], ['media', 'repeater']) && ! is_array($component['data'][$fieldName])) {
                $component['data'][$fieldName] = [];
            }
        }

        return $component;
    }

    public function getComponentDefinition(string $type): ?array
    {
        return collect($this->availableComponents)->firstWhere('type', $type);
    }

    public function render(): View
    {
        return view('daylight::livewire.page-builder.page-builder');
    }
}
