<?php
declare(strict_types=1);

namespace PpPhp\Core\Designer\Dashboard;

final class DesignerDashboardDefinition
{
    public function __construct(
        private readonly string $dashboardId,
        private readonly string $title,
        private readonly DesignerDashboardLayout $layout = new DesignerDashboardLayout(),
        private readonly array $widgets = [],
        private readonly array $meta = []
    ) {}

    public static function create(string $dashboardId, string $title = '', string $layout = '4+4+4'): self
    {
        return new self(
            $dashboardId,
            $title !== '' ? $title : self::humanize($dashboardId),
            DesignerDashboardLayout::preset($layout),
            [],
            ['version' => '1.0.0', 'createdAt' => date('c')]
        );
    }

    public static function fromArray(array $data): self
    {
        return new self(
            (string) ($data['dashboardId'] ?? $data['id'] ?? 'dashboard'),
            (string) ($data['title'] ?? 'Dashboard'),
            DesignerDashboardLayout::fromArray((array) ($data['layout'] ?? [])),
            (array) ($data['widgets'] ?? $data['components'] ?? []),
            (array) ($data['meta'] ?? [])
        );
    }

    public function addWidget(DesignerDashboardWidget $widget): self
    {
        return new self($this->dashboardId, $this->title, $this->layout, array_merge($this->widgets, [$widget->toArray()]), $this->meta);
    }

    public function moveWidget(string $widgetId, int $position): self
    {
        $widgets = $this->widgets;
        $found = null;

        foreach ($widgets as $i => $widget) {
            if (($widget['id'] ?? '') === $widgetId) {
                $found = $widget;
                array_splice($widgets, $i, 1);
                break;
            }
        }

        if ($found !== null) {
            $position = max(0, min($position, count($widgets)));
            array_splice($widgets, $position, 0, [$found]);
        }

        return new self($this->dashboardId, $this->title, $this->layout, array_values($widgets), $this->meta);
    }

    public function duplicateWidget(string $widgetId): self
    {
        $widgets = $this->widgets;

        foreach ($widgets as $widget) {
            if (($widget['id'] ?? '') === $widgetId) {
                $copy = $widget;
                $copy['id'] = $widgetId . '_copy_1';
                $copy['name'] = $copy['id'];
                $copy['meta'] = array_replace((array) ($copy['meta'] ?? []), ['duplicatedFrom' => $widgetId, 'duplicatedAt' => date('c')]);
                $widgets[] = $copy;
                break;
            }
        }

        return new self($this->dashboardId, $this->title, $this->layout, array_values($widgets), $this->meta);
    }

    public function deleteWidget(string $widgetId): self
    {
        return new self(
            $this->dashboardId,
            $this->title,
            $this->layout,
            array_values(array_filter($this->widgets, static fn (array $widget): bool => ($widget['id'] ?? '') !== $widgetId)),
            $this->meta
        );
    }

    public function toComponent(): array
    {
        return [
            'id' => $this->dashboardId,
            'name' => $this->dashboardId,
            'type' => 'dashboard',
            'label' => $this->title,
            'props' => $this->toArray(),
            'children' => [],
            'events' => ['widgetClick', 'refresh', 'filterChange'],
            'meta' => ['designerRuntime' => 'dashboard', 'version' => '1.0.0'],
        ];
    }

    public function toPage(): array
    {
        return [
            'version' => '1.0',
            'pageId' => $this->dashboardId,
            'pageType' => 'dashboard',
            'title' => $this->title,
            'components' => [$this->toComponent()],
            'meta' => ['designerRuntime' => 'dashboard-page', 'generatedAt' => date('c')],
        ];
    }

    public function toArray(): array
    {
        return [
            'dashboardId' => $this->dashboardId,
            'id' => $this->dashboardId,
            'type' => 'dashboard',
            'title' => $this->title,
            'layout' => $this->layout->toArray(),
            'widgets' => $this->widgets,
            'meta' => $this->meta,
            'widgetCount' => count($this->widgets),
        ];
    }

    private static function humanize(string $value): string
    {
        return ucwords(str_replace(['_', '-'], ' ', $value));
    }
}
