import { useMemo, useState } from 'react';
import type { ProcessNode } from '../../types/process';
import { extractStreamInfo } from '../../utils/streamInfo';

interface Props {
  processes: ProcessNode[];
  groups: number[][];
  groupNames: string[];
}

interface BubbleData {
  id: string;
  label: string;       // stream name
  process: string;     // process group name
  subprocess: string;  // subprocess name
  tin: number | null;
  tout: number | null;
  Q: number | null;
  CP: number | null;
  mdot: number | null;
  cp: number | null;
  type: 'hot' | 'cold' | null;
}

/** Return an RGBA fill color matching the Streamlit logic:
 *  hot stream → red tones, cold → blue tones; intensity by max temp */
function getBubbleColor(b: BubbleData): { fill: string; stroke: string } {
  if (b.tin == null || b.tout == null || b.type == null) {
    return { fill: 'rgba(150,150,150,0.55)', stroke: '#666' };
  }
  const maxTemp = Math.max(b.tin, b.tout);
  const strong = maxTemp > 100;
  if (b.type === 'hot') {
    return strong
      ? { fill: 'rgba(255,40,40,0.75)', stroke: '#b00' }
      : { fill: 'rgba(255,130,130,0.75)', stroke: '#c44' };
  } else {
    return strong
      ? { fill: 'rgba(40,80,255,0.75)', stroke: '#00b' }
      : { fill: 'rgba(120,160,255,0.75)', stroke: '#44a' };
  }
}

export default function StreamBubbleChart({ processes, groups, groupNames }: Props) {
  const [hovered, setHovered] = useState<string | null>(null);

  const bubbles = useMemo<BubbleData[]>(() => {
    const result: BubbleData[] = [];
    groups.forEach((subIdxs, gIdx) => {
      const gName = groupNames[gIdx] || `Process ${gIdx + 1}`;
      subIdxs.forEach((si) => {
        const sub = processes[si];
        if (!sub) return;

        const processStreams = (streamList: ProcessNode['streams'], subName: string) => {
          (streamList || []).forEach((s, sIdx) => {
            const info = extractStreamInfo(s as Record<string, any>);
            result.push({
              id: `g${gIdx}-s${si}-${sIdx}`,
              label: s.name || `Stream ${sIdx + 1}`,
              process: gName,
              subprocess: subName,
              tin: info.tin,
              tout: info.tout,
              Q: info.Q,
              CP: info.CP,
              mdot: info.mdot,
              cp: info.cp,
              type: info.type,
            });
          });
        };

        processStreams(sub.streams, sub.name);
        (sub.children || []).forEach((child) => {
          processStreams(child.streams, `${sub.name} > ${child.name}`);
        });
      });
    });
    return result;
  }, [processes, groups, groupNames]);

  // Global min-max Q scaling for radius  (matching Streamlit: r_min=6, r_max=20px)
  const { qMin, qRange } = useMemo(() => {
    const Qs = bubbles.map((b) => b.Q ?? 0).filter((q) => q > 0);
    const qMin = Qs.length ? Math.min(...Qs) : 0;
    const qMax = Qs.length ? Math.max(...Qs) : 1;
    return { qMin, qRange: qMax === qMin ? 1 : qMax - qMin };
  }, [bubbles]);

  const R_MIN = 8;
  const R_MAX = 28;

  const getRadius = (Q: number | null) => {
    if (!Q || Q <= 0) return R_MIN;
    return R_MIN + Math.round(((Q - qMin) / qRange) * (R_MAX - R_MIN));
  };

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

  // ---- Layout: pack bubbles in a horizontal strip, grouped by process ----
  const GAP = 12;
  const PADDING = 20;
  const HEIGHT = 120;

  // Compute x positions
  let cx = PADDING + R_MAX;
  const positioned = bubbles.map((b, i) => {
    const r = getRadius(b.Q);
    const x = cx;
    cx += r * 2 + GAP;
    return { ...b, r, x, y: HEIGHT / 2, i };
  });
  const svgWidth = cx + PADDING;

  const hoveredBubble = hovered ? positioned.find((b) => b.id === hovered) : null;

  return (
    <div className="card mt-md" style={{ overflowX: 'auto' }}>
      <h4 style={{ fontSize: 12, marginBottom: 4 }}>
        Stream Power Overview
        <span style={{ fontWeight: 400, fontSize: 11, color: 'var(--color-muted)', marginLeft: 8 }}>
          circle size = heat power Q (kW) · color = stream type
        </span>
      </h4>

      {/* Legend */}
      <div style={{ display: 'flex', gap: 16, marginBottom: 6, flexWrap: 'wrap' }}>
        {[
          { label: 'Hot &gt;100°C', fill: 'rgba(255,40,40,0.75)', stroke: '#b00' },
          { label: 'Hot ≤100°C', fill: 'rgba(255,130,130,0.75)', stroke: '#c44' },
          { label: 'Cold &gt;100°C', fill: 'rgba(40,80,255,0.75)', stroke: '#00b' },
          { label: 'Cold ≤100°C', fill: 'rgba(120,160,255,0.75)', stroke: '#44a' },
          { label: 'Unknown', fill: 'rgba(150,150,150,0.55)', stroke: '#666' },
        ].map((l) => (
          <span key={l.label} style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 10 }}>
            <svg width={12} height={12}>
              <circle cx={6} cy={6} r={5} fill={l.fill} stroke={l.stroke} strokeWidth={1} />
            </svg>
            <span dangerouslySetInnerHTML={{ __html: l.label }} />
          </span>
        ))}
      </div>

      <svg
        width={svgWidth}
        height={HEIGHT}
        style={{ display: 'block', minWidth: svgWidth }}
      >
        {positioned.map((b) => {
          const { fill, stroke } = getBubbleColor(b);
          const isHov = hovered === b.id;
          return (
            <g
              key={b.id}
              onMouseEnter={() => setHovered(b.id)}
              onMouseLeave={() => setHovered(null)}
              style={{ cursor: 'pointer' }}
            >
              <circle
                cx={b.x}
                cy={b.y}
                r={b.r + (isHov ? 3 : 0)}
                fill={fill}
                stroke={isHov ? '#fff' : stroke}
                strokeWidth={isHov ? 2 : 1}
                style={{ transition: 'r 0.15s, stroke 0.15s' }}
              />
            </g>
          );
        })}
      </svg>

      {/* Tooltip / detail panel */}
      {hoveredBubble && (
        <div
          style={{
            marginTop: 6,
            padding: '8px 12px',
            background: 'var(--bg)',
            borderRadius: 6,
            border: '1px solid var(--border)',
            fontSize: 11,
            display: 'grid',
            gridTemplateColumns: 'repeat(auto-fill, minmax(130px, 1fr))',
            gap: '4px 16px',
          }}
        >
          <strong style={{ gridColumn: '1/-1', fontSize: 12 }}>
            {hoveredBubble.label}
            <span style={{ fontWeight: 400, marginLeft: 8, color: 'var(--color-muted)' }}>
              {hoveredBubble.process} / {hoveredBubble.subprocess}
            </span>
          </strong>
          <span>Tin: <b>{hoveredBubble.tin != null ? `${hoveredBubble.tin.toFixed(1)} °C` : '—'}</b></span>
          <span>Tout: <b>{hoveredBubble.tout != null ? `${hoveredBubble.tout.toFixed(1)} °C` : '—'}</b></span>
          {hoveredBubble.CP != null && (
            <span>CP: <b>{hoveredBubble.CP.toFixed(2)} kW/K</b></span>
          )}
          {hoveredBubble.mdot != null && (
            <span>ṁ: <b>{hoveredBubble.mdot.toFixed(2)}</b></span>
          )}
          {hoveredBubble.cp != null && (
            <span>cp: <b>{hoveredBubble.cp.toFixed(3)}</b></span>
          )}
          <span>
            Q: <b style={{ color: hoveredBubble.Q != null ? 'var(--color-primary, #6c8ebf)' : undefined }}>
              {hoveredBubble.Q != null ? `${hoveredBubble.Q.toFixed(1)} kW` : 'N/A'}
            </b>
          </span>
        </div>
      )}
    </div>
  );
}
