<?php
declare(strict_types=1);

namespace PpPhp\Core\Designer\Layout;

final class DesignerGridRow
{
    public function __construct(
        private readonly string $rowId,
        private readonly array $columns = [],
        private readonly array $settings = [],
        private readonly array $style = []
    ) {}

    public static function create(string $rowId, array $spans = [12]): self
    {
        $columns = [];
        foreach (array_values($spans) as $index => $span) {
            $columns[] = DesignerGridColumn::create($rowId . '_col_' . ($index + 1), (int) $span);
        }
        return new self($rowId, self::normalizeColumns($columns), ['gap' => 12, 'wrap' => true, 'align' => 'stretch', 'justify' => 'start']);
    }

    public static function fromArray(array $data): self
    {
        $columns = [];
        foreach ((array) ($data['columns'] ?? $data['cells'] ?? []) as $column) {
            if (is_array($column)) {
                $columns[] = DesignerGridColumn::fromArray($column);
            }
        }
        return new self((string) ($data['rowId'] ?? $data['id'] ?? 'row'), self::normalizeColumns($columns), (array) ($data['settings'] ?? []), (array) ($data['style'] ?? []));
    }

    public function rowId(): string { return $this->rowId; }
    public function columns(): array { return $this->columns; }

    public function split(int $columnIndex, array $spans): self
    {
        $columns = $this->columns;
        if (!isset($columns[$columnIndex])) return $this;
        $replacement = [];
        foreach (array_values($spans) as $index => $span) {
            $replacement[] = DesignerGridColumn::create($this->rowId . '_col_' . ($columnIndex + $index + 1), (int) $span);
        }
        array_splice($columns, $columnIndex, 1, $replacement);
        return new self($this->rowId, self::normalizeColumns($columns), $this->settings, $this->style);
    }

    public function merge(int $fromIndex, int $toIndex): self
    {
        $columns = $this->columns;
        if (!isset($columns[$fromIndex], $columns[$toIndex]) || $fromIndex === $toIndex) return $this;
        $start = min($fromIndex, $toIndex);
        $end = max($fromIndex, $toIndex);
        $span = 0; $components = [];
        for ($i = $start; $i <= $end; $i++) {
            $span += $columns[$i]->span();
            $components = array_merge($components, $columns[$i]->components());
        }
        array_splice($columns, $start, $end - $start + 1, [DesignerGridColumn::create($this->rowId . '_col_' . ($start + 1), min(12, $span), 0, $components)]);
        return new self($this->rowId, self::normalizeColumns($columns), $this->settings, $this->style);
    }

    public function resize(int $columnIndex, int $span): self
    {
        $columns = $this->columns;
        if (!isset($columns[$columnIndex])) return $this;
        $columns[$columnIndex] = $columns[$columnIndex]->resized($span);
        return new self($this->rowId, self::normalizeColumns($columns), $this->settings, $this->style);
    }

    public function reorder(int $fromIndex, int $toIndex): self
    {
        $columns = $this->columns;
        if (!isset($columns[$fromIndex]) || $toIndex < 0 || $toIndex >= count($columns)) return $this;
        $column = $columns[$fromIndex];
        array_splice($columns, $fromIndex, 1);
        array_splice($columns, $toIndex, 0, [$column]);
        return new self($this->rowId, self::normalizeColumns($columns), $this->settings, $this->style);
    }

    public function totalSpan(): int
    {
        return array_sum(array_map(static fn (DesignerGridColumn $column): int => $column->span(), $this->columns));
    }

    public function valid(): bool
    {
        return $this->columns !== [] && $this->totalSpan() <= 12;
    }

    public function toComponent(): array
    {
        $columns = array_map(static fn (DesignerGridColumn $column): array => $column->toArray(), $this->columns);
        return [
            'id' => $this->rowId,
            'type' => 'row',
            'label' => 'Row',
            'props' => ['cells' => $columns, 'columns' => $columns, 'settings' => $this->settings],
            'style' => $this->style,
            'children' => [],
            'meta' => ['layoutEngine' => '12-grid', 'totalSpan' => $this->totalSpan()],
        ];
    }

    public function toArray(): array
    {
        return ['rowId' => $this->rowId, 'id' => $this->rowId, 'columns' => array_map(static fn (DesignerGridColumn $column): array => $column->toArray(), $this->columns), 'settings' => $this->settings, 'style' => $this->style, 'valid' => $this->valid(), 'totalSpan' => $this->totalSpan()];
    }

    private static function normalizeColumns(array $columns): array
    {
        $columns = array_values(array_filter($columns, static fn ($column): bool => $column instanceof DesignerGridColumn));
        if ($columns === []) return [DesignerGridColumn::create('col_1', 12)];
        $total = array_sum(array_map(static fn (DesignerGridColumn $column): int => $column->span(), $columns));
        if ($total <= 12) return $columns;
        $count = count($columns);
        $base = intdiv(12, $count);
        $remaining = 12 - ($base * $count);
        return array_map(static fn (DesignerGridColumn $column, int $index): DesignerGridColumn => $column->resized($base + ($index < $remaining ? 1 : 0)), $columns, array_keys($columns));
    }
}
