<?php

declare(strict_types=1);

namespace PpPhp\Core\Designer\Selection;

final class DesignerSelectionTreeBuilder
{
    public function build(array $page): array
    {
        $rootTarget = DesignerSelectionTarget::page($page);

        $children = [];
        foreach ((array) ($page['components'] ?? []) as $index => $component) {
            if (is_array($component)) {
                $children[] = $this->componentNode($component, ['components', $index]);
            }
        }

        return (new DesignerSelectionTreeNode(
            $rootTarget->targetId(),
            $rootTarget->label(),
            'page',
            $rootTarget->toArray(),
            $children
        ))->toArray();
    }

    private function componentNode(array $component, array $path): array
    {
        $target = DesignerSelectionTarget::component($component, $path);
        $children = [];

        foreach ($this->partNodes($component, $path) as $partNode) {
            $children[] = $partNode;
        }

        foreach ((array) ($component['children'] ?? []) as $index => $child) {
            if (is_array($child)) {
                $children[] = $this->componentNode($child, array_merge($path, ['children', $index]));
            }
        }

        return DesignerSelectionTreeNode::fromTarget($target, $children)->toArray();
    }

    private function partNodes(array $component, array $path): array
    {
        $type = (string) ($component['type'] ?? '');
        $props = (array) ($component['props'] ?? []);
        $nodes = [];

        if (in_array($type, ['table_grid', 'data_grid', 'grid'], true)) {
            foreach (['toolbar' => 'Toolbar', 'search' => 'Search', 'table' => 'Table', 'footer' => 'Footer'] as $part => $label) {
                $nodes[] = DesignerSelectionTreeNode::fromTarget(
                    DesignerSelectionTarget::partTarget($component, $part, $part, $label, array_merge($path, ['parts', $part]))
                )->toArray();
            }

            foreach ((array) ($props['columns'] ?? []) as $index => $column) {
                $field = (string) ($column['field'] ?? $column['name'] ?? 'column_' . $index);
                $label = (string) ($column['label'] ?? $column['title'] ?? $field);

                $nodes[] = DesignerSelectionTreeNode::fromTarget(
                    DesignerSelectionTarget::partTarget($component, 'column', $field, 'Column: ' . $label, array_merge($path, ['props', 'columns', $index]), [
                        'field' => $field,
                        'columnIndex' => $index,
                    ])
                )->toArray();
            }

            foreach ((array) ($props['actions'] ?? []) as $index => $action) {
                $id = (string) ($action['id'] ?? 'action_' . $index);
                $label = (string) ($action['label'] ?? $action['name'] ?? $id);

                $nodes[] = DesignerSelectionTreeNode::fromTarget(
                    DesignerSelectionTarget::partTarget($component, 'action_button', $id, 'Action: ' . $label, array_merge($path, ['props', 'actions', $index]), [
                        'actionId' => $id,
                        'actionIndex' => $index,
                    ])
                )->toArray();
            }

            foreach ((array) ($props['bulkActions'] ?? []) as $index => $action) {
                $id = (string) ($action['id'] ?? 'bulk_action_' . $index);
                $label = (string) ($action['label'] ?? $action['name'] ?? $id);

                $nodes[] = DesignerSelectionTreeNode::fromTarget(
                    DesignerSelectionTarget::partTarget($component, 'bulk_action', $id, 'Bulk: ' . $label, array_merge($path, ['props', 'bulkActions', $index]), [
                        'actionId' => $id,
                        'actionIndex' => $index,
                    ])
                )->toArray();
            }
        }

        if ($type === 'row') {
            foreach ((array) ($props['cells'] ?? []) as $index => $cell) {
                $cellId = (string) ($cell['id'] ?? 'cell_' . $index);

                $nodes[] = DesignerSelectionTreeNode::fromTarget(
                    DesignerSelectionTarget::partTarget($component, 'cell', $cellId, 'Cell ' . ($index + 1), array_merge($path, ['props', 'cells', $index]), [
                        'cellId' => $cellId,
                        'cellIndex' => $index,
                    ])
                )->toArray();
            }
        }

        return $nodes;
    }
}
