// trends.jsx — Per-hydrant trend view
// Groups saved tests by residual reading location (rounded to ~11m), shows
// a sparkline of available GPM over time so you can spot supply degradation.

const { useMemo: __tUseM } = React;

// Coarse grouping fingerprint — same hydrant if its residual location matches
// to 4 decimal places (~11m). Falls back to label, then to "untagged".
function __trendKey(reading) {
  if (reading.location) {
    return `loc:${reading.location.lat.toFixed(4)},${reading.location.lng.toFixed(4)}`;
  }
  const lbl = (reading.label || '').trim().toLowerCase();
  if (lbl) return `label:${lbl}`;
  return null;
}

// Flatten history into per-hydrant groups. Each group is one residual location
// (or labeled hydrant) with the timeline of readings taken there.
function buildHydrantGroups(history) {
  const groups = new Map();
  const push = (key, displayLabel, location, reading) => {
    if (!groups.has(key)) {
      groups.set(key, { id: key, label: displayLabel || 'Unlabeled', location, readings: [] });
    } else if (!groups.get(key).location && location) {
      groups.get(key).location = location;
    }
    groups.get(key).readings.push(reading);
  };

  history.forEach((h) => {
    const results = h.results || [];
    const residuals = h.residualReadings;

    if (Array.isArray(residuals) && residuals.length > 0) {
      residuals.forEach((r) => {
        const key = __trendKey(r);
        if (!key) return;
        const result = results.find((x) => x.residualId === r.id);
        push(key,
          r.label || (r.location ? null : 'Untagged'),
          r.location || null, {
            ts: h.ts,
            available: result?.available ?? null,
            classCode: result?.classCode ?? null,
            residualPsi: Number(r.residualPsi) || null,
            testGpm: h.testGpm,
            staticPsi: h.staticPsi,
            target: h.target,
            entry: h,
            entryLabel: h.label || '',
            residualLabel: r.label || '',
          });
      });
    } else if (h.location || h.residualPsi != null) {
      // Legacy single-hydrant entry
      const key = h.location
        ? `loc:${h.location.lat.toFixed(4)},${h.location.lng.toFixed(4)}`
        : h.label ? `label:${h.label.toLowerCase().trim()}` : null;
      if (!key) return;
      push(key, h.label || 'Legacy', h.location || null, {
        ts: h.ts, available: h.available, classCode: null,
        residualPsi: Number(h.residualPsi) || null,
        testGpm: h.testGpm, staticPsi: h.staticPsi, target: h.target,
        entry: h, entryLabel: h.label || '', residualLabel: '',
      });
    }
  });

  const out = [...groups.values()];
  out.forEach((g) => g.readings.sort((a, b) => a.ts - b.ts));
  out.sort((a, b) => {
    const aMax = a.readings[a.readings.length - 1]?.ts || 0;
    const bMax = b.readings[b.readings.length - 1]?.ts || 0;
    return bMax - aMax;
  });
  return out;
}

// ─────────────────────────────────────────────────────────────────────────────
// Sparkline — small SVG plot of available GPM over time

function Sparkline({ readings, width = 200, height = 56 }) {
  const pad = 4;
  const w = width - pad * 2;
  const h = height - pad * 2;
  const vals = readings.map((r) => r.available).filter((v) => v != null && isFinite(v));
  if (vals.length === 0) return null;
  const min = Math.min(...vals);
  const max = Math.max(...vals);
  const range = Math.max(max - min, 1);
  const tMin = readings[0].ts;
  const tMax = readings[readings.length - 1].ts;
  const tRange = Math.max(tMax - tMin, 1);

  const points = readings.map((r) => {
    if (r.available == null) return null;
    const x = pad + ((r.ts - tMin) / tRange) * w;
    const y = pad + (1 - (r.available - min) / range) * h;
    return { x, y, available: r.available };
  }).filter(Boolean);

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

  const path = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(' ');
  const areaPath = `${path} L${points[points.length - 1].x.toFixed(1)},${height - pad} L${points[0].x.toFixed(1)},${height - pad} Z`;

  return (
    <svg viewBox={`0 0 ${width} ${height}`} style={{ width: '100%', height, display: 'block' }}>
      <path d={areaPath} fill="var(--accent)" opacity="0.12" />
      <path d={path} fill="none" stroke="var(--accent)" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" />
      {points.map((p, i) => (
        <circle key={i} cx={p.x} cy={p.y} r={i === points.length - 1 ? 3 : 2}
          fill={i === points.length - 1 ? 'var(--accent)' : '#15151a'}
          stroke="var(--accent)" strokeWidth="1.2" />
      ))}
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Trend card — one per hydrant

function fmtGpm(n) {
  if (n == null || !isFinite(n)) return '—';
  return Math.round(Number(n)).toLocaleString('en-US');
}

function TrendCard({ group, onLoad }) {
  const readings = group.readings;
  const latest = readings[readings.length - 1];
  const first = readings[0];
  const delta = (latest?.available != null && first?.available != null && readings.length > 1)
    ? latest.available - first.available
    : null;
  const pctDelta = (delta != null && first.available)
    ? (delta / first.available) * 100
    : null;

  const lastDate = new Date(latest.ts);
  const firstDate = new Date(first.ts);

  const trendTone = pctDelta == null ? '#7a7a84'
    : pctDelta < -10 ? '#f87171'
    : pctDelta < -3  ? '#f5a524'
    : pctDelta >  3  ? '#4ade80'
    : '#a8a8b2';

  return (
    <div style={trendCardStyles.card}>
      <div style={trendCardStyles.top}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={trendCardStyles.label}>{group.label}</div>
          {group.location && (
            <div style={trendCardStyles.coord} className="mono">
              {group.location.lat.toFixed(5)}, {group.location.lng.toFixed(5)}
            </div>
          )}
        </div>
        <div style={trendCardStyles.countPill} className="mono">
          {readings.length} test{readings.length === 1 ? '' : 's'}
        </div>
      </div>

      <div style={trendCardStyles.statRow}>
        <div style={trendCardStyles.stat}>
          <div style={trendCardStyles.statLbl}>Latest</div>
          <div style={trendCardStyles.statVal} className="mono">
            {fmtGpm(latest.available)}
            <span style={trendCardStyles.statUnit}>GPM</span>
          </div>
          <div style={trendCardStyles.statDate}>
            {lastDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}
          </div>
        </div>

        {readings.length > 1 && (
          <div style={trendCardStyles.stat}>
            <div style={trendCardStyles.statLbl}>Change</div>
            <div style={{ ...trendCardStyles.statVal, color: trendTone }} className="mono">
              {delta != null
                ? `${delta >= 0 ? '+' : ''}${fmtGpm(Math.abs(delta))}`
                : '—'}
              {pctDelta != null && (
                <span style={{ ...trendCardStyles.statUnit, color: trendTone }}>
                  {pctDelta >= 0 ? '+' : ''}{pctDelta.toFixed(1)}%
                </span>
              )}
            </div>
            <div style={trendCardStyles.statDate}>
              since {firstDate.toLocaleDateString('en-US', { month: 'short', year: '2-digit' })}
            </div>
          </div>
        )}
      </div>

      {readings.length > 1 && (
        <div style={trendCardStyles.sparkWrap}>
          <Sparkline readings={readings} />
        </div>
      )}

      <div style={trendCardStyles.timeline}>
        {readings.slice().reverse().map((r, i) => (
          <button key={i} onClick={() => onLoad(r.entry)} style={trendCardStyles.timelineRow}>
            <span style={trendCardStyles.timelineDate} className="mono">
              {new Date(r.ts).toLocaleDateString('en-US', { year: '2-digit', month: 'short', day: 'numeric' })}
            </span>
            <span style={trendCardStyles.timelineMeta} className="mono">
              S{fmtGpm(r.staticPsi)}/R{fmtGpm(r.residualPsi)}
            </span>
            <span style={trendCardStyles.timelineVal} className="mono">
              {fmtGpm(r.available)} GPM
            </span>
            {r.classCode && (
              <span style={{ ...trendCardStyles.classChip, color: TONE_COLORS[r.classCode] || '#a8a8b2',
                             borderColor: TONE_COLORS[r.classCode] || '#a8a8b2' }} className="mono">
                {r.classCode}
              </span>
            )}
          </button>
        ))}
      </div>
    </div>
  );
}

const TONE_COLORS = { AA: '#5dadec', A: '#4ade80', B: '#f5a524', C: '#f87171' };

const trendCardStyles = {
  card: { background: '#15151a', border: '1px solid #26262e', borderRadius: 14,
          padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 12 },
  top: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10 },
  label: { fontSize: 14, fontWeight: 600, color: '#fafaf7', overflow: 'hidden',
           textOverflow: 'ellipsis', whiteSpace: 'nowrap' },
  coord: { fontSize: 11, color: '#7a7a84', marginTop: 2 },
  countPill: { padding: '3px 8px', background: '#101014', border: '1px solid #2a2a31',
               borderRadius: 999, fontSize: 11, fontWeight: 600, color: '#a8a8b2',
               whiteSpace: 'nowrap' },
  statRow: { display: 'flex', gap: 20 },
  stat: { display: 'flex', flexDirection: 'column', gap: 1 },
  statLbl: { fontSize: 10, fontWeight: 600, color: '#7a7a84', letterSpacing: '0.05em',
             textTransform: 'uppercase' },
  statVal: { fontSize: 22, fontWeight: 500, letterSpacing: '-0.02em',
             color: 'var(--accent)', display: 'flex', alignItems: 'baseline', gap: 5 },
  statUnit: { fontSize: 11, color: '#7a7a84', fontWeight: 500 },
  statDate: { fontSize: 10.5, color: '#5a5a62' },
  sparkWrap: { padding: '4px 0', borderTop: '1px solid #1f1f25', borderBottom: '1px solid #1f1f25' },
  timeline: { display: 'flex', flexDirection: 'column', gap: 2 },
  timelineRow: { display: 'grid', gridTemplateColumns: '90px 1fr auto auto', gap: 8, alignItems: 'center',
                 padding: '5px 8px', background: 'transparent', border: 0, borderRadius: 6,
                 color: 'inherit', cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit' },
  timelineDate: { fontSize: 11.5, color: '#a8a8b2' },
  timelineMeta: { fontSize: 11, color: '#6a6a72' },
  timelineVal: { fontSize: 12, fontWeight: 600, color: '#fafaf7' },
  classChip: { fontSize: 9.5, fontWeight: 700, padding: '1px 5px', border: '1px solid',
               borderRadius: 3, letterSpacing: '0.04em' },
};

// ─────────────────────────────────────────────────────────────────────────────
// TrendsView — full tab

function TrendsView({ history, onLoadEntry }) {
  const groups = __tUseM(() => buildHydrantGroups(history), [history]);

  if (groups.length === 0) {
    return (
      <div style={trendsStyles.empty}>
        <div style={{ fontSize: 38, marginBottom: 8, color: '#3a3a44' }}>◔</div>
        <div style={{ fontSize: 14, color: '#a8a8b2' }}>No saved tests yet</div>
        <div style={{ fontSize: 12, color: '#5a5a62', marginTop: 6, maxWidth: 280, textAlign: 'center' }}>
          Save a test from the Test tab. After two or more tests at the same hydrant,
          you'll see its supply trend here.
        </div>
      </div>
    );
  }

  const totalReadings = groups.reduce((s, g) => s + g.readings.length, 0);

  return (
    <div style={trendsStyles.wrap}>
      <div style={trendsStyles.summary}>
        <div style={trendsStyles.summaryStat}>
          <span style={trendsStyles.summaryVal} className="mono">{groups.length}</span>
          <span style={trendsStyles.summaryLbl}>hydrant{groups.length === 1 ? '' : 's'}</span>
        </div>
        <div style={trendsStyles.summaryStat}>
          <span style={trendsStyles.summaryVal} className="mono">{totalReadings}</span>
          <span style={trendsStyles.summaryLbl}>reading{totalReadings === 1 ? '' : 's'}</span>
        </div>
        <div style={trendsStyles.summaryHint}>Grouped by location · 11 m radius</div>
      </div>

      {groups.map((g) => (
        <TrendCard key={g.id} group={g} onLoad={onLoadEntry} />
      ))}

      <div style={{ height: 20 }} />
    </div>
  );
}

const trendsStyles = {
  wrap: { padding: '16px 18px 32px', display: 'flex', flexDirection: 'column', gap: 12 },
  empty: { padding: '80px 24px', display: 'flex', flexDirection: 'column',
           alignItems: 'center', justifyContent: 'center', textAlign: 'center' },
  summary: { display: 'flex', alignItems: 'center', gap: 18,
             padding: '12px 14px', background: '#101014', border: '1px solid #1f1f25',
             borderRadius: 10, marginBottom: 4 },
  summaryStat: { display: 'flex', alignItems: 'baseline', gap: 5 },
  summaryVal: { fontSize: 18, fontWeight: 600, color: '#fafaf7', letterSpacing: '-0.02em' },
  summaryLbl: { fontSize: 11.5, color: '#7a7a84' },
  summaryHint: { marginLeft: 'auto', fontSize: 10.5, color: '#5a5a62',
                 letterSpacing: '0.04em', textTransform: 'uppercase' },
};

Object.assign(window, { TrendsView });
