<?php
declare(strict_types=1);

namespace PpPhp\Core\Designer\Navigation;

final class DesignerNavigationItem
{
    public function __construct(
        private readonly string $id,
        private readonly string $label,
        private readonly string $type = 'page',
        private readonly string $target = '',
        private readonly string $icon = '',
        private readonly array $children = [],
        private readonly array $permissions = [],
        private readonly array $meta = []
    ) {}

    public static function create(string $id, string $label = '', string $type = 'page', string $target = '', string $icon = ''): self
    {
        return new self(
            $id,
            $label !== '' ? $label : self::humanize($id),
            $type,
            $target !== '' ? $target : $id,
            $icon !== '' ? $icon : self::defaultIcon($id, $type),
            [],
            [],
            ['createdAt' => date('c')]
        );
    }

    public static function fromArray(array $data): self
    {
        $children = [];
        foreach ((array) ($data['children'] ?? []) as $child) {
            if (is_array($child)) {
                $children[] = self::fromArray($child)->toArray();
            }
        }

        return new self(
            (string) ($data['id'] ?? 'nav_item'),
            (string) ($data['label'] ?? self::humanize((string) ($data['id'] ?? 'nav_item'))),
            (string) ($data['type'] ?? 'page'),
            (string) ($data['target'] ?? $data['route'] ?? ''),
            (string) ($data['icon'] ?? ''),
            $children,
            (array) ($data['permissions'] ?? []),
            (array) ($data['meta'] ?? [])
        );
    }

    public function id(): string { return $this->id; }

    public function withChild(DesignerNavigationItem $item): self
    {
        return new self($this->id, $this->label, $this->type, $this->target, $this->icon, array_merge($this->children, [$item->toArray()]), $this->permissions, $this->meta);
    }

    public function withoutChild(string $id): self
    {
        return new self(
            $this->id,
            $this->label,
            $this->type,
            $this->target,
            $this->icon,
            array_values(array_filter($this->children, static fn (array $child): bool => ($child['id'] ?? '') !== $id)),
            $this->permissions,
            $this->meta
        );
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'label' => $this->label,
            'type' => $this->type,
            'target' => $this->target,
            'route' => $this->target,
            'icon' => $this->icon,
            'children' => $this->children,
            'permissions' => $this->permissions,
            'meta' => $this->meta,
        ];
    }

    private static function defaultIcon(string $id, string $type): string
    {
        return match ($type) {
            'dashboard' => 'bi-speedometer2',
            'section' => 'bi-folder',
            'external' => 'bi-box-arrow-up-right',
            'action' => 'bi-lightning',
            default => match ($id) {
                'dashboard', 'home' => 'bi-house',
                'customers', 'users' => 'bi-people',
                'orders' => 'bi-bag',
                'settings' => 'bi-gear',
                'reports' => 'bi-bar-chart',
                default => 'bi-circle',
            },
        };
    }

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