<?php
// components/CampaignFlow/MergeViz.php
namespace Components\CampaignFlow;

use Components\Base;

/**
 * Render a merge/converge block consisting of two (or more) horizontal lanes (top/bottom)
 * that converge into a single trunk on the right.
 *
 * Input shape (example):
 *   [
 *     'type' => 'merge',
 *     'top' => FlowItems,     // array from FlowBuilder::toArray()
 *     'bottom' => FlowItems,  // array from FlowBuilder::toArray()
 *     'gap' => 'md',          // optional spacing between lanes: sm|md|lg
 *   ]
 *
 * Notes:
 * - Orientation currently supports only horizontal parent flows.
 * - This component focuses on stable layout; the main flow continuation connector is
 *   rendered by FlowViz (a connector is inserted after the merge block when needed).
 */
class MergeViz extends Base
{
    public static function render(array $merge, array $opts = []): string
    {
        $size = $opts['size'] ?? 'md'; // xs|sm|md|lg
        $editable = (bool)($opts['editable'] ?? false);

        $gap = (string)($merge['gap'] ?? 'md');
        if ($gap === 'sm') {
            $gapY = 'gap-y-4';
            $gapFactorY = 4;
        } elseif ($gap === 'lg') {
            $gapY = 'gap-y-12';
            $gapFactorY = 12;
        } else {
            $gapY = 'gap-y-8';
            $gapFactorY = 8;
        }

        // Lane paddings so elbows have some vertical room to look rounded
        if ($size === 'xs') {
            $lanePadY = 'py-1';
        } elseif ($size === 'sm') {
            $lanePadY = 'py-2';
        } elseif ($size === 'lg') {
            $lanePadY = 'py-4';
        } else {
            $lanePadY = 'py-3';
        }

        // Right column width hosting the trunk + elbows
        if ($size === 'xs') {
            $rightW = 20;
        } elseif ($size === 'sm') {
            $rightW = 28;
        } elseif ($size === 'lg') {
            $rightW = 36;
        } else {
            $rightW = 32;
        }

        // Compose lanes list: prefer 'lanes' (N lanes), fallback to 'top'/'bottom'
        $lanesItems = [];
        if (isset($merge['lanes']) && is_array($merge['lanes'])) {
            foreach ($merge['lanes'] as $li) {
                $lanesItems[] = is_array($li) ? $li : [];
            }
        } else {
            $topItems = is_array($merge['top'] ?? null) ? $merge['top'] : [];
            $bottomItems = is_array($merge['bottom'] ?? null) ? $merge['bottom'] : [];
            if ($topItems !== [] || $bottomItems !== []) {
                $lanesItems = [$topItems, $bottomItems];
            }
        }
        if (!$lanesItems) {
            return '';
        }

        // Prepare per-lane HTML using FlowViz recursion
        $laneHtmls = [];
        foreach ($lanesItems as $li) {
            $laneHtmls[] = FlowViz::render($li, [
                'orientation' => 'horizontal',
                'size' => $size,
                'editable' => $editable,
                'addTail' => $opts['addTail'] ?? null,
            ]);
        }

        // Elbow box width per size
        if ($size === 'xs') {
            $elbowW = 16;   // w-4
            $radiusTR = 'rounded-tr-md';
            $radiusBR = 'rounded-br-md';
        } elseif ($size === 'sm') {
            $elbowW = 20;   // w-5
            $radiusTR = 'rounded-tr-lg';
            $radiusBR = 'rounded-br-lg';
        } elseif ($size === 'lg') {
            $elbowW = 28;   // ~w-7
            $radiusTR = 'rounded-tr-2xl';
            $radiusBR = 'rounded-br-2xl';
        } else {
            // md
            $elbowW = 24;   // w-6
            $radiusTR = 'rounded-tr-xl';
            $radiusBR = 'rounded-br-xl';
        }

        $rightCenter =  (int)floor($rightW / 2) ;

        // Build HTML using output buffering (ob_start) to comply with inline HTML guidelines
        $gridCls = 'grid ' . $gapY . ' ' . $lanePadY . '';
        $gridStyle = 'grid-template-columns: 1fr ' . $rightW . 'px';

        ob_start();
        ?>
        <div class="relative z-10" style="width: 100%; max-width: 100%">
            <!-- Outro horizontal line from trunk center to the right edge (connects to the main flow) -->
            <div class="pointer-events-none absolute right-0 top-1/2 -translate-y-1/2  h-px bg-flow"
                 style="width: <?= (int)($rightW - $rightCenter) ?>px">
                <div class="absolute size-2 rounded-full bg-flow -left-1 -top-1"></div>
            </div>

            <div class="<?= self::h($gridCls) ?>" style="<?= self::h($gridStyle) ?>">
                <?php
                $rowCount = count($laneHtmls);
                foreach ($laneHtmls as $i => $laneHtml):
                    $isFirst = ($i === 0);
                    $isAboveCenter = ($i < ($rowCount - 1) / 2);
                    $isCenter = ($i === ($rowCount - 1) / 2);
                    $isLast = ($i === $rowCount - 1);
                    $isBelowCenter = (!$isLast) ? ($i > ($rowCount - 1) / 2) : false;
                    ?>

                    <!-- Lane content (left), aligned to the right edge so it meets the merge connector -->
                    <div class="relative flex items-center justify-end w-full">
                        <?= $laneHtml ?>
                    </div>

                    <!-- Trunk + elbows (right) -->
                    <div class="relative -z-1">
                        <?php if ($isFirst || $isAboveCenter): ?>
                            <div class="pointer-events-none absolute <?= self::h($radiusTR) ?> border-t border-r border-flow"
                                 style="left: <?= (int)($rightCenter - $elbowW) ?>px; top: calc(50% - 0.5px); width: <?= (int)$elbowW ?>px; height: <?= (int)$elbowW ?>px"></div>
                        <?php elseif ($isCenter): ?>
                            <div class="pointer-events-none absolute top-1/2 -translate-y-1/2 h-px bg-flow"
                                 style="left: 0; width: <?= (int)$rightCenter ?>px"></div>
                        <?php elseif ($isBelowCenter || $isLast): ?>
                            <div class="pointer-events-none absolute <?= self::h($radiusBR) ?> border-b border-r border-flow"
                                 style="left: <?= (int)($rightCenter - $elbowW) ?>px; top: calc(50% + 0.5px - <?= (int)$elbowW ?>px); width: <?= (int)$elbowW ?>px; height: <?= (int)$elbowW ?>px"></div>
                        <?php endif; ?>

                        <?php
                        // Vertical trunk segments between lanes (span into the grid gaps)
                        if ($isFirst): ?>
                            <div class="border-l border-flow absolute"
                                 style="left: <?= (int)$rightCenter -1 ?>px; height: calc(50% + (var(--spacing) * 0.5 * <?= (int)$gapFactorY ?>)); top: calc(50% + (var(--spacing) * 0.5 * <?= (int)$gapFactorY ?>));"></div>
                        <?php elseif ($isAboveCenter): ?>
                            <div class="border-l border-flow absolute"
                                 style="left: <?= (int)$rightCenter -1 ?>px; height: calc(100% + (var(--spacing) * 1 * <?= (int)$gapFactorY ?>));"></div>
                        <?php elseif ($isCenter): ?>
                            <div class="border-l border-flow absolute"
                                 style="left: <?= (int)$rightCenter -1 ?>px; height: calc(100% + (var(--spacing) * 1 * <?= (int)$gapFactorY ?>));"></div>
                        <?php elseif ($isBelowCenter): ?>
                            <div class="border-l border-flow absolute"
                                 style="left: <?= (int)$rightCenter -1 ?>px; height: calc(100% + (var(--spacing) * 1 * <?= (int)$gapFactorY ?>));"></div>
                        <?php elseif ($isLast): ?>
                            <div class="border-l border-flow absolute"
                                 style="left: <?= (int)$rightCenter -1 ?>px; height: calc(100% - (var(--spacing) * 0.5 * <?= (int)$gapFactorY ?>)); top: calc(-50%);"></div>
                        <?php endif; ?>
                    </div>
                <?php endforeach; ?>
            </div>
        </div>
        <?php
        return (string)ob_get_clean();
    }
}
