'use client';

import { memo, useMemo, useState } from 'react';
import type { SankeyRawData } from '@/app/lib/sankey/types';
import { computeSankeyLayout, makeLinkPath } from '@/app/lib/sankey/geometry';
import { formatDisplayNumber } from '@/app/lib/format';
import { DIAGRAM } from '@/app/lib/sankey/config';
import { useT } from './ContentProvider';
import { TrendingIcon } from './icons';
import { Badge, Frame } from './ui';

export const SankeyDiagram = memo(function SankeyDiagram({ data, unverified = false }: { data: SankeyRawData; /** Figures came from the model's text, not from the database. */ unverified?: boolean }) {
  const t = useT();
  const [tooltip, setTooltip] = useState<{ x: number; y: number; text: string } | null>(null);
  const W = DIAGRAM.width, H = Math.max(DIAGRAM.minHeight, data.nodes.length * DIAGRAM.heightPerNode);
  // Hovering updates the tooltip state on every mouse move; the layout depends only on the data.
  const { nodes, links, nodeMap, maxLayer } = useMemo(() => {
    const layout = computeSankeyLayout(data, W, H);
    return {
      ...layout,
      nodeMap: new Map(layout.nodes.map(n => [n.id, n])),
      maxLayer: layout.nodes.reduce((max, n) => Math.max(max, n.layer), 0),
    };
  }, [data, W, H]);

  return (
    <Frame className="bg-stripe">
      {/* Header */}
      <div className="flex items-center gap-2.5 border-b border-line px-3.5 py-2.5">
        <Badge tone="blue" icon={<TrendingIcon size={11} color="var(--color-accent-blue)" />}>{t('sankey.title')}</Badge>
        <span className="text-[13px] text-muted">{t('sankey.stats', { nodes: data.nodes.length, flows: data.links.length })}</span>
        {unverified && (
          <span className="rounded-md border border-warning/25 bg-warning/10 px-2 py-0.5 text-[12px] font-semibold uppercase tracking-[0.1em] text-warning-ink">
            {t('sankey.unverified')}
          </span>
        )}
      </div>
      <div className="overflow-x-auto p-4">
        <svg viewBox={`0 0 ${W} ${H}`} width="100%" className="overflow-visible" style={{ minWidth: DIAGRAM.minRenderedWidth, maxHeight: DIAGRAM.maxRenderedHeight }} onMouseLeave={() => setTooltip(null)}>
          <defs>
            {links.map((l, i) => {
              const tgt = nodeMap.get(l.target);
              return (
                <linearGradient key={`grad-${i}`} id={`lg-${i}`} x1="0%" y1="0%" x2="100%" y2="0%">
                  <stop key="a" offset="0%"   stopColor={l.color}           stopOpacity={0.5} />
                  <stop key="b" offset="100%" stopColor={tgt?.color ?? l.color} stopOpacity={0.5} />
                </linearGradient>
              );
            })}
            <filter id="glow">
              <feGaussianBlur stdDeviation="2" result="blur" />
              <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
            </filter>
          </defs>

          {links.map((l, i) => (
            <path
              key={`link-${i}`}
              d={makeLinkPath(l, nodeMap)}
              fill={`url(#lg-${i})`}
              className="cursor-pointer opacity-40 transition-[opacity] duration-200 hover:opacity-75"
              onMouseEnter={e => {
                const svgEl = e.currentTarget.closest('svg') as SVGSVGElement;
                const pt = svgEl.createSVGPoint();
                pt.x = e.clientX; pt.y = e.clientY;
                const svgP = pt.matrixTransform(svgEl.getScreenCTM()!.inverse());
                setTooltip({ x: svgP.x, y: svgP.y - 16, text: `${nodeMap.get(l.source)?.label} → ${nodeMap.get(l.target)?.label}: ${formatDisplayNumber(l.value)}` });
              }}
              onMouseLeave={() => setTooltip(null)}
            />
          ))}

          {nodes.map(node => {
            const midY = (node.y0 + node.y1) / 2;
            const isRight = node.layer === maxLayer;
            return (
              <g key={`node-${node.id}`}>
                <rect x={node.x0 - 3} y={node.y0 - 3} width={node.x1 - node.x0 + 6} height={node.y1 - node.y0 + 6} rx={7} fill={node.color} fillOpacity={0.12} />
                <rect x={node.x0} y={node.y0} width={node.x1 - node.x0} height={node.y1 - node.y0} rx={4} fill={node.color} />
                <text x={isRight ? node.x0 - 10 : node.x1 + 10} y={midY - 7} textAnchor={isRight ? 'end' : 'start'} dominantBaseline="middle" fontSize={14} fontWeight={600} className="fill-ink font-sans">{node.label}</text>
                <text x={isRight ? node.x0 - 10 : node.x1 + 10} y={midY + 9} textAnchor={isRight ? 'end' : 'start'} dominantBaseline="middle" fontSize={12} className="fill-muted font-mono">{formatDisplayNumber(node.value)}</text>
              </g>
            );
          })}

          {tooltip && (() => {
            const w = tooltip.text.length * 6.2 + 24;
            return (
              <g transform={`translate(${tooltip.x - w / 2}, ${tooltip.y - 32})`}>
                <rect width={w} height={26} rx={8} strokeWidth={1} className="fill-tint stroke-accent/40" />
                <text x={w / 2} y={16} textAnchor="middle" fontSize={13} className="fill-ink font-sans">{tooltip.text}</text>
              </g>
            );
          })()}
        </svg>
      </div>
    </Frame>
  );
});
