import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import {
  BarChart,
  Bar,
  XAxis,
  YAxis,
  Tooltip,
  ResponsiveContainer,
  CartesianGrid,
  ReferenceLine,
  ComposedChart,
  ScatterChart,
  Scatter,
  Line,
  Cell,
} from 'recharts'
import { api } from '../../utils/api'
import { getStatusColor, getStatusBg } from '../../utils/interpret'
import { EmptySection, PeriodSelector, SectionHeader } from './historyPageChrome'
import { HISTORY_OVERVIEW_VIZ_PAGE_FULL, normalizeHistoryOverviewVizConfig } from '../../widgetSystem/historyOverviewVizConfig'

function overviewSectionTone(sec) {
  const kpis = sec.kpi_short || []
  if (kpis.some((k) => k.status === 'bad')) return 'bad'
  if (kpis.some((k) => k.status === 'warn')) return 'warn'
  const interp = sec.interpretation_short || []
  if (interp.some((x) => x.status === 'bad')) return 'bad'
  if (interp.some((x) => x.status === 'warn')) return 'warn'
  const heur = sec.heuristic_short || []
  if (heur.some((h) => h.status === 'warn')) return 'warn'
  return 'good'
}

function overviewConfidenceUi(conf) {
  if (conf === 'high') return { label: 'Datenlage: gut', tone: 'good', hint: 'Ausreichend Messpunkte für sinnvolle Kurzinfos.' }
  if (conf === 'medium') return { label: 'Datenlage: mittel', tone: 'warn', hint: 'Einzelne Bereiche sind noch dünn besetzt.' }
  return { label: 'Datenlage: dünn', tone: 'bad', hint: 'Mehr Einträge verbessern die Aussagekraft.' }
}

function chartJsScatterPoints(payload) {
  const raw = payload?.data?.datasets?.[0]?.data || []
  if (!Array.isArray(raw)) return []
  return raw.map((p) => ({ x: Number(p.x), y: Number(p.y) }))
}

function lagDetailsToCurve(meta) {
  let ld = meta?.lag_details
  if (!Array.isArray(ld) || ld.length === 0) {
    const m = String(meta?.metric || '').toUpperCase()
    if (m === 'HRV' && Array.isArray(meta?.lag_details_hrv)) ld = meta.lag_details_hrv
    else if (m === 'RHR' && Array.isArray(meta?.lag_details_rhr)) ld = meta.lag_details_rhr
    else {
      const h = meta?.lag_details_hrv
      const r = meta?.lag_details_rhr
      const hl = Array.isArray(h) ? h.length : 0
      const rl = Array.isArray(r) ? r.length : 0
      if (hl >= rl && hl > 0) ld = h
      else if (rl > 0) ld = r
      else ld = []
    }
  }
  if (!Array.isArray(ld) || ld.length === 0) return []
  return ld
    .map((d) => ({
      lag: Number(d?.lag),
      r: d?.r == null || d?.r === '' ? null : Number(d.r),
      n_pairs: d?.n_pairs != null ? Number(d.n_pairs) : null,
    }))
    .filter((d) => Number.isFinite(d.lag) && d.r != null && Number.isFinite(d.r))
    .sort((a, b) => a.lag - b.lag)
}

function driverBarFromStatus(st) {
  const s = String(st || '').toLowerCase()
  if (s.includes('hinder')) return { v: -1, fill: 'var(--danger)' }
  if (s.includes('förder') || s.includes('foerder')) return { v: 1, fill: 'var(--accent)' }
  return { v: 0.15, fill: '#6B7280' }
}

function chartJsBarRows(payload, fallbackDrivers) {
  const labels = payload?.data?.labels || []
  const values = payload?.data?.datasets?.[0]?.data || []
  const colors = payload?.data?.datasets?.[0]?.backgroundColor
  if (labels.length && values.length) {
    return labels.map((name, i) => ({
      name: name.length > 42 ? `${name.slice(0, 40)}…` : name,
      value: Number(values[i]),
      fill: Array.isArray(colors) ? colors[i] : Number(values[i]) < 0 ? '#EF4444' : '#1D9E75',
    }))
  }
  if (fallbackDrivers?.length) {
    return fallbackDrivers.map((d) => {
      const { v, fill } = driverBarFromStatus(d.status)
      return {
        name: String(d.factor || '—').length > 40 ? `${String(d.factor).slice(0, 38)}…` : String(d.factor || '—'),
        value: v,
        fill,
        subtitle: d.reason,
      }
    })
  }
  return []
}

function CorrelationScatterTile({ title, accent, payload }) {
  const meta = payload?.metadata || {}
  const pts = chartJsScatterPoints(payload)
  const curve = lagDetailsToCurve(meta)
  const hasChart = pts.length > 0 && meta.correlation != null
  const r = Number(meta.correlation)
  const strength =
    !Number.isFinite(r) ? 'bad' : Math.abs(r) >= 0.35 ? 'good' : Math.abs(r) >= 0.15 ? 'warn' : 'bad'
  const bestLag = meta.best_lag_days != null ? Number(meta.best_lag_days) : null
  const maxLagAxis = curve.length ? Math.max(14, ...curve.map((d) => d.lag), bestLag || 0) : 28

  return (
    <div
      className="card"
      style={{
        marginBottom: 0,
        padding: 10,
        borderLeft: `4px solid ${getStatusColor(strength)}`,
      }}
    >
      <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--text1)', marginBottom: 4 }}>{title}</div>
      <div style={{ fontSize: 10, color: 'var(--text3)', lineHeight: 1.35, marginBottom: 6 }}>
        r = {meta.correlation != null ? Number(meta.correlation).toFixed(3) : '—'}
        {meta.best_lag_days != null ? ` · bestes Lag ${meta.best_lag_days} T` : ''}
        {meta.metric ? ` · ${meta.metric}` : ''}
        {meta.confidence ? ` · ${meta.confidence}` : ''}
      </div>
      {!hasChart ? (
        <>
          <div style={{ fontSize: 11, color: 'var(--text3)', marginBottom: curve.length ? 8 : 0 }}>
            {meta.message || 'Keine Daten für diese Korrelation.'}
          </div>
          {curve.length > 0 && (
            <div style={{ fontSize: 10, color: 'var(--text3)', marginBottom: 6 }}>
              Lag-Sweep (kein Lag mit ≥15 Paaren): r über Lags — nur zur Einordnung.
            </div>
          )}
          {curve.length > 0 && (
            <ResponsiveContainer width="100%" height={120}>
              <ComposedChart data={curve} margin={{ top: 4, right: 6, bottom: 4, left: -14 }}>
                <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
                <XAxis dataKey="lag" type="number" domain={[0, maxLagAxis]} tick={{ fontSize: 9, fill: 'var(--text3)' }} label={{ value: 'Lag (T)', fontSize: 9, fill: 'var(--text3)', offset: -2 }} />
                <YAxis dataKey="r" domain={[-1, 1]} tick={{ fontSize: 9, fill: 'var(--text3)' }} width={36} label={{ value: 'r', fontSize: 9, fill: 'var(--text3)', angle: -90 }} />
                <ReferenceLine y={0} stroke="var(--text3)" strokeDasharray="4 4" />
                <Tooltip
                  contentStyle={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, fontSize: 10 }}
                  formatter={(v, _n, item) => [`r = ${Number(v).toFixed(3)}`, `Lag ${item?.payload?.lag} T · n = ${item?.payload?.n_pairs ?? '—'}`]}
                />
                <Line type="monotone" dataKey="r" stroke={accent} strokeWidth={2} dot={{ r: 3, fill: accent }} isAnimationActive={false} />
              </ComposedChart>
            </ResponsiveContainer>
          )}
        </>
      ) : curve.length >= 1 ? (
        <>
          <div style={{ fontSize: 9, color: 'var(--text3)', marginBottom: 4 }}>
            Kurve: Pearson-r je Lag (Tage); starker Punkt = gewähltes bestes Lag.
          </div>
          <ResponsiveContainer width="100%" height={132}>
            <ComposedChart data={curve} margin={{ top: 4, right: 6, bottom: 4, left: -14 }}>
              <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
              <XAxis dataKey="lag" type="number" domain={[0, maxLagAxis]} tick={{ fontSize: 9, fill: 'var(--text3)' }} />
              <YAxis dataKey="r" domain={[-1, 1]} tick={{ fontSize: 9, fill: 'var(--text3)' }} width={36} />
              <ReferenceLine y={0} stroke="var(--text3)" strokeDasharray="4 4" />
              <Tooltip
                contentStyle={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, fontSize: 10 }}
                formatter={(v, _n, item) => [`r = ${Number(v).toFixed(3)}`, `Lag ${item?.payload?.lag} T · n = ${item?.payload?.n_pairs ?? '—'}`]}
              />
              <Line
                type="monotone"
                dataKey="r"
                stroke={accent}
                strokeWidth={2}
                isAnimationActive={false}
                dot={(props) => {
                  const { cx, cy, payload: pl } = props
                  if (cx == null || cy == null || !pl) return null
                  const isBest = bestLag != null && Number(pl.lag) === bestLag
                  return (
                    <circle
                      cx={cx}
                      cy={cy}
                      r={isBest ? 6 : 3.5}
                      fill={isBest ? 'var(--surface)' : accent}
                      stroke={isBest ? accent : 'none'}
                      strokeWidth={isBest ? 2.5 : 0}
                    />
                  )
                }}
              />
            </ComposedChart>
          </ResponsiveContainer>
        </>
      ) : (
        <ResponsiveContainer width="100%" height={118}>
          <ScatterChart margin={{ top: 2, right: 4, bottom: 2, left: -18 }}>
            <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
            <XAxis type="number" dataKey="x" domain={[0, 28]} tick={{ fontSize: 9, fill: 'var(--text3)' }} />
            <YAxis type="number" dataKey="y" domain={[-1, 1]} tick={{ fontSize: 9, fill: 'var(--text3)' }} />
            <ReferenceLine y={0} stroke="var(--text3)" strokeDasharray="4 4" />
            <Tooltip contentStyle={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, fontSize: 10 }} />
            <Scatter name="r" data={pts} fill={accent} />
          </ScatterChart>
        </ResponsiveContainer>
      )}
      {meta.interpretation ? (
        <div style={{ fontSize: 10, color: 'var(--text2)', marginTop: 6, lineHeight: 1.4 }}>{meta.interpretation}</div>
      ) : null}
    </div>
  )
}

function DriversImpactTile({ payload, driversFallback }) {
  const meta = payload?.metadata || {}
  const rows = chartJsBarRows(payload, driversFallback)
  if (!rows.length) {
    return (
      <div className="card" style={{ padding: 12, borderLeft: '4px solid var(--border)' }}>
        <div style={{ fontSize: 11, fontWeight: 700, marginBottom: 6 }}>C4 Einflussfaktoren</div>
        <div style={{ fontSize: 11, color: 'var(--text3)' }}>{meta.message || 'Keine Treiber-Daten.'}</div>
      </div>
    )
  }
  const h = Math.min(220, Math.max(96, rows.length * 34))
  return (
    <div className="card" style={{ padding: 10, borderLeft: '4px solid var(--accent)' }}>
      <div style={{ fontSize: 11, fontWeight: 700, marginBottom: 6 }}>C4 Einflussfaktoren</div>
      <ResponsiveContainer width="100%" height={h}>
        <BarChart data={rows} layout="vertical" margin={{ left: 2, right: 6, top: 2, bottom: 2 }}>
          <XAxis type="number" domain={[-1.2, 1.2]} tick={{ fontSize: 9 }} />
          <YAxis type="category" dataKey="name" width={112} tick={{ fontSize: 9, fill: 'var(--text2)' }} />
          <Tooltip
            content={({ active, payload: pp }) => {
              if (!active || !pp?.length) return null
              const p = pp[0].payload
              return (
                <div
                  style={{
                    background: 'var(--surface)',
                    border: '1px solid var(--border)',
                    padding: '8px 10px',
                    borderRadius: 8,
                    fontSize: 11,
                    maxWidth: 280,
                  }}
                >
                  <div style={{ fontWeight: 600 }}>{p.name}</div>
                  {p.subtitle ? <div style={{ marginTop: 4, color: 'var(--text2)', lineHeight: 1.4 }}>{p.subtitle}</div> : null}
                </div>
              )
            }}
          />
          <Bar dataKey="value" radius={[0, 4, 4, 0]}>
            {rows.map((e, i) => (
              <Cell key={i} fill={e.fill} />
            ))}
          </Bar>
        </BarChart>
      </ResponsiveContainer>
    </div>
  )
}

/**
 * Verlauf «Gesamt» / Dashboard-Widget: Layer-2b history-overview-viz (+ chart_payloads C1–C4).
 *
 * @param {object} props
 * @param {import('react').ReactNode} [props.footer]
 * @param {number} [props.externalPeriod] — feste Tage (Widget); sonst interner PeriodSelector (30…9999)
 * @param {boolean} [props.hidePeriodSelector]
 * @param {boolean} [props.embedded]
 * @param {Record<string, unknown>} [props.visibility] — normalisierte Widget-Config; undefined = Verlauf volle Ansicht
 */
export default function HistoryOverviewVizSection({
  footer = null,
  externalPeriod,
  hidePeriodSelector = false,
  embedded = false,
  visibility: visibilityProp,
}) {
  const navigate = useNavigate()
  const [period, setPeriod] = useState(30)
  const [bundle, setBundle] = useState(null)
  const [err, setErr] = useState(null)
  const [loading, setLoading] = useState(true)

  const effPeriod = externalPeriod != null ? externalPeriod : period
  const daysReq = effPeriod === 9999 ? 3650 : effPeriod

  useEffect(() => {
    let cancelled = false
    setLoading(true)

    const attachCharts = (overview, c1, c2, c3, c4) => {
      if (!cancelled) {
        setBundle({ overview, chartC1: c1, chartC2: c2, chartC3: c3, chartC4: c4 })
        setErr(null)
      }
    }

    const run = async () => {
      try {
        const overview = await api.getHistoryOverviewViz(daysReq)
        const cp = overview?.chart_payloads
        if (cp && cp.c1_weight_energy != null && cp.c2_protein_lbm != null && cp.c3_load_vitals != null && cp.c4_recovery_performance != null) {
          attachCharts(overview, cp.c1_weight_energy, cp.c2_protein_lbm, cp.c3_load_vitals, cp.c4_recovery_performance)
        } else {
          const [chartC1, chartC2, chartC3, chartC4] = await Promise.all([
            api.getWeightEnergyCorrelationChart(14),
            api.getLbmProteinCorrelationChart(14),
            api.getLoadVitalsCorrelationChart(14),
            api.getRecoveryPerformanceChart(),
          ])
          attachCharts(overview, chartC1, chartC2, chartC3, chartC4)
        }
      } catch (e) {
        if (!cancelled) setErr(e.message || 'Laden fehlgeschlagen')
      } finally {
        if (!cancelled) setLoading(false)
      }
    }

    run()
    return () => {
      cancelled = true
    }
  }, [daysReq])

  if (loading) {
    return (
      <div>
        {!embedded && <SectionHeader title="📊 Gesamtansicht" />}
        {!hidePeriodSelector && externalPeriod == null && <PeriodSelector value={period} onChange={setPeriod} />}
        <div className="spinner" style={{ margin: 24 }} />
      </div>
    )
  }
  if (err) {
    return (
      <div>
        {!embedded && <SectionHeader title="📊 Gesamtansicht" />}
        {!hidePeriodSelector && externalPeriod == null && <PeriodSelector value={period} onChange={setPeriod} />}
        <div className="card" style={{ color: 'var(--danger)', marginTop: 8 }}>{err}</div>
      </div>
    )
  }

  const data = bundle?.overview
  const chartC1 = bundle?.chartC1
  const chartC2 = bundle?.chartC2
  const chartC3 = bundle?.chartC3
  const chartC4 = bundle?.chartC4

  const lag = data?.lag_correlations || {}
  const c4drivers = lag.recovery_performance?.drivers || []
  const sections = data?.sections || []
  const confUi = overviewConfidenceUi(data?.confidence)
  const vis =
    visibilityProp != null ? normalizeHistoryOverviewVizConfig(visibilityProp) : HISTORY_OVERVIEW_VIZ_PAGE_FULL

  return (
    <div>
      {!embedded && <SectionHeader title="📊 Gesamtansicht" />}
      {!hidePeriodSelector && externalPeriod == null && <PeriodSelector value={period} onChange={setPeriod} />}

      {vis.show_confidence_banner && (
        <div
          style={{
            display: 'flex',
            flexWrap: 'wrap',
            alignItems: 'center',
            gap: 10,
            marginBottom: 14,
            padding: '10px 12px',
            borderRadius: 12,
            border: '1px solid var(--border)',
            background: getStatusBg(confUi.tone),
            borderLeft: `5px solid ${getStatusColor(confUi.tone)}`,
          }}
        >
          <span style={{ fontSize: 20, lineHeight: 1 }}>{confUi.tone === 'good' ? '●' : confUi.tone === 'warn' ? '◐' : '○'}</span>
          <div style={{ flex: 1, minWidth: 200 }}>
            <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text1)' }}>{confUi.label}</div>
            <div style={{ fontSize: 11, color: 'var(--text2)', marginTop: 2 }}>{confUi.hint}</div>
          </div>
        </div>
      )}

      {vis.show_intro_blurb && (
        <p style={{ fontSize: 11, color: 'var(--text3)', lineHeight: 1.45, marginBottom: 14 }}>
          KPIs und Texte kommen aus den Layer-2b-Bundles (Körper, Ernährung, Fitness, Erholung).{' '}
          <strong>Ehem. «Korrelation»-Charts</strong> (Bilanz, Protein/Mager, Kurz-Einordnung) liegen unter{' '}
          <button type="button" className="btn btn-secondary" style={{ fontSize: 11, padding: '2px 8px' }} onClick={() => navigate('/history', { state: { tab: 'nutrition' } })}>
            Ernährung
          </button>
          . Die Kacheln C1–C4 entsprechen denselben Chart.js-Payloads wie <code style={{ fontSize: 10 }}>/api/charts/*</code> (bei aktuellem Backend im Overview-Bundle enthalten).
        </p>
      )}

      {vis.show_area_summaries && (sections.length === 0 ? (
        <EmptySection text="Keine Bereichsdaten." />
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 10 }}>
          {sections.map((sec) => {
            const tone = overviewSectionTone(sec)
            const stripe = getStatusColor(tone)
            const badgeBg = getStatusBg(tone)
            return (
              <div
                key={sec.id}
                style={{
                  borderRadius: 12,
                  border: '1px solid var(--border)',
                  borderLeft: `5px solid ${stripe}`,
                  background: 'var(--surface)',
                  padding: '12px 12px 12px 14px',
                  boxShadow: tone === 'bad' ? '0 0 0 1px rgba(216,90,48,0.12)' : undefined,
                }}
              >
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 8, marginBottom: 8 }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <span
                      style={{
                        display: 'inline-flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                        minWidth: 30,
                        height: 30,
                        borderRadius: 10,
                        fontSize: 13,
                        fontWeight: 800,
                        color: stripe,
                        background: badgeBg,
                      }}
                    >
                      {tone === 'good' ? '✓' : tone === 'warn' ? '!' : '!!'}
                    </span>
                    <div style={{ fontSize: 15, fontWeight: 700 }}>{sec.title}</div>
                  </div>
                  <button
                    type="button"
                    className="btn btn-secondary"
                    style={{ fontSize: 11, padding: '4px 10px', flexShrink: 0 }}
                    onClick={() => navigate('/history', { state: { tab: sec.tab_id } })}
                  >
                    Öffnen
                  </button>
                </div>
                <div style={{ fontSize: 12, color: 'var(--text2)', marginBottom: 10, lineHeight: 1.45 }}>{sec.summary_line}</div>

                {(sec.kpi_short || []).length > 0 && (
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(128px, 1fr))', gap: 8, marginBottom: 8 }}>
                    {(sec.kpi_short || []).map((k, i) => (
                      <div
                        key={i}
                        style={{
                          padding: '8px 10px',
                          borderRadius: 10,
                          background: getStatusBg(k.status || 'good'),
                          border: `1px solid ${getStatusColor(k.status || 'good')}55`,
                        }}
                      >
                        <div style={{ fontSize: 9, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{k.category}</div>
                        <div style={{ fontSize: 14, fontWeight: 700, color: getStatusColor(k.status || 'good'), marginTop: 2 }}>{k.value}</div>
                        {k.sublabel ? <div style={{ fontSize: 9, color: 'var(--text3)', marginTop: 2 }}>{k.sublabel}</div> : null}
                      </div>
                    ))}
                  </div>
                )}

                {(sec.interpretation_short || []).map((it, i) => (
                  <div key={`in-${i}`} style={{ fontSize: 11, marginBottom: 6, paddingLeft: 8, borderLeft: `3px solid ${getStatusColor(it.status || 'good')}` }}>
                    <strong style={{ color: 'var(--text1)' }}>{it.title}</strong>
                    <div style={{ color: 'var(--text2)', marginTop: 2, lineHeight: 1.4 }}>{it.detail}</div>
                  </div>
                ))}
                {(sec.heuristic_short || []).map((h, i) => (
                  <div key={`he-${i}`} style={{ fontSize: 11, marginTop: 6, padding: '6px 8px', borderRadius: 8, background: 'var(--surface2)' }}>
                    <strong style={{ color: h.status === 'warn' ? 'var(--warn)' : 'var(--accent)' }}>{h.title}</strong>
                    <div style={{ fontSize: 10, color: 'var(--text2)', marginTop: 2 }}>{h.detail}</div>
                  </div>
                ))}
                {(sec.insights_short || []).map((ins, i) => (
                  <div key={`is-${i}`} style={{ fontSize: 11, marginTop: 6, color: 'var(--text2)', lineHeight: 1.45 }}>
                    <strong>{ins.title}</strong>
                    <div>{ins.body}</div>
                  </div>
                ))}
              </div>
            )
          })}
        </div>
      ))}

      {vis.show_correlation_c1_c3 && (
        <>
          <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--text1)', margin: '18px 0 10px' }}>Lag-Korrelationen (C1–C3)</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: 10 }}>
            <CorrelationScatterTile title="C1 Energiebilanz ↔ Gewicht" accent="#1D9E75" payload={chartC1} />
            <CorrelationScatterTile title="C2 Protein ↔ Magermasse" accent="#3B82F6" payload={chartC2} />
            <CorrelationScatterTile title="C3 Last ↔ HRV/RHR" accent="#F59E0B" payload={chartC3} />
          </div>
        </>
      )}

      {vis.show_drivers_c4 && (
        <>
          <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--text1)', margin: '18px 0 10px' }}>Einflussfaktoren (C4)</div>
          <DriversImpactTile payload={chartC4} driversFallback={c4drivers} />
        </>
      )}

      {footer}
    </div>
  )
}
