import { useEffect, useRef, useState } from 'react';
import { type DistributionPreview } from '@/types';

interface Props {
    distribution: DistributionPreview;
    bucketRefs: React.RefObject<Map<string, HTMLElement> | null>;
    containerRef: React.RefObject<HTMLDivElement | null>;
    incomeRef: React.RefObject<HTMLDivElement | null>;
}

interface LinePosition {
    bucketId: string;
    amount: number;
    bucketY: number;
    bucketRight: number;
    incomeLeft: number;
    incomeY: number;
}

const centsToDollars = (cents: number): string => `$${(cents / 100).toFixed(0)}`;

export default function DistributionLines({ distribution, bucketRefs, containerRef, incomeRef }: Props) {
    const [positions, setPositions] = useState<LinePosition[]>([]);
    const svgRef = useRef<SVGSVGElement>(null);

    useEffect(() => {
        const measure = () => {
            const container = containerRef.current;
            const income = incomeRef.current;
            if (!container || !income) return;

            const containerRect = container.getBoundingClientRect();
            const incomeRect = income.getBoundingClientRect();
            const incomeLeft = incomeRect.left - containerRect.left;
            const incomeCenterY = incomeRect.top + incomeRect.height / 2 - containerRect.top;

            const lines: LinePosition[] = [];

            for (const alloc of distribution.allocations) {
                const el = bucketRefs.current?.get(alloc.bucket_id);
                if (!el) continue;

                const bucketRect = el.getBoundingClientRect();
                const bucketRight = bucketRect.right - containerRect.left;
                const bucketY = bucketRect.top + bucketRect.height / 2 - containerRect.top;

                lines.push({
                    bucketId: alloc.bucket_id,
                    amount: alloc.allocated_amount,
                    bucketY,
                    bucketRight,
                    incomeLeft,
                    incomeY: incomeCenterY,
                });
            }

            setPositions(lines);
        };

        requestAnimationFrame(measure);

        const observer = new ResizeObserver(measure);
        if (containerRef.current) observer.observe(containerRef.current);

        return () => observer.disconnect();
    }, [distribution, bucketRefs, containerRef, incomeRef]);

    if (positions.length === 0) return null;

    // Trunk X position: midpoint between rightmost bucket and income panel
    const trunkX = positions.length > 0
        ? (Math.max(...positions.map(p => p.bucketRight)) + positions[0].incomeLeft) / 2
        : 0;
    const incomeY = positions[0]?.incomeY ?? 0;
    const allYs = [...positions.map(p => p.bucketY), incomeY];
    const trunkTop = Math.min(...allYs);
    const trunkBottom = Math.max(...allYs);

    return (
        <svg
            ref={svgRef}
            className="absolute inset-0 w-full h-full pointer-events-none"
            style={{ zIndex: 10 }}
        >
            {/* Vertical trunk from income to span all bucket Y positions */}
            <line
                x1={trunkX}
                y1={trunkTop}
                x2={trunkX}
                y2={trunkBottom}
                stroke="rgb(239, 68, 68)"
                strokeWidth={2}
                strokeOpacity={0.6}
            />

            {/* Horizontal line from trunk to income panel */}
            <line
                x1={trunkX}
                y1={positions[0].incomeY}
                x2={positions[0].incomeLeft}
                y2={positions[0].incomeY}
                stroke="rgb(239, 68, 68)"
                strokeWidth={2}
                strokeOpacity={0.6}
            />

            {/* Branch lines from trunk to each bucket */}
            {positions.map((pos) => {
                const isZero = pos.amount === 0;
                const opacity = isZero ? 0.2 : 0.8;
                const label = centsToDollars(pos.amount);

                return (
                    <g key={pos.bucketId}>
                        {/* Horizontal branch: trunk → bucket */}
                        <line
                            x1={trunkX}
                            y1={pos.bucketY}
                            x2={pos.bucketRight + 8}
                            y2={pos.bucketY}
                            stroke="rgb(239, 68, 68)"
                            strokeWidth={2}
                            strokeOpacity={opacity}
                        />
                        {/* Arrow tip */}
                        <polygon
                            points={`${pos.bucketRight + 8},${pos.bucketY - 4} ${pos.bucketRight},${pos.bucketY} ${pos.bucketRight + 8},${pos.bucketY + 4}`}
                            fill="rgb(239, 68, 68)"
                            fillOpacity={opacity}
                        />
                        {/* Amount label */}
                        <text
                            x={(trunkX + pos.bucketRight) / 2}
                            y={pos.bucketY - 8}
                            textAnchor="middle"
                            fill="rgb(239, 68, 68)"
                            fillOpacity={opacity}
                            fontSize={12}
                            fontFamily="monospace"
                            fontWeight="bold"
                        >
                            {label}
                        </text>
                    </g>
                );
            })}
        </svg>
    );
}
