/* SkyOps — Asset Manager: cross-site trends, benchmarks, financial modelling.
   Persona: executive overseeing 10-100+ sites. */

const { useState: useStateAM, useMemo: useMemoAM } = React;

/* ── Financial assumptions ────────────────────── */
const FIN = {
  price_eur_mwh: 52,        // PPA + pool blended
  cf_solar: 0.22,           // capacity factor Iberia
  cf_wind: 0.28,
  om_eur_mw_yr: 9800,       // O&M fixed
  discount: 0.07,
  mic_cost_eur: 4800,       // cost per MIC (drone inspection)
};

/* Derive site-level financial metrics deterministically */
function computeSiteFin(site) {
  const cf = site.type === "Wind" ? FIN.cf_wind : FIN.cf_solar;
  const mwh_yr = site.capacity_mw * 8760 * cf;
  const revenue_yr = mwh_yr * FIN.price_eur_mwh;
  const om_yr = site.capacity_mw * FIN.om_eur_mw_yr;
  // Revenue at risk: health gap × availability loss estimate
  const health_gap = Math.max(0, 100 - site.health);
  const avail_loss = health_gap * 0.0018; // % production lost per health-point
  const rar_yr = revenue_yr * avail_loss;
  // NPV of repair vs degrade over 10y
  const insp = (window.INSPECTIONS || []).filter(i => i.siteId === site.id);
  const open_critical = insp.reduce((a, i) => a + (i.critical || 0), 0);
  const repair_cost = open_critical * 1850 + 12000; // panel replace + soft cost
  const npv_fix = -repair_cost + rar_yr * 7.0;      // 7-year present value factor
  const npv_degrade = -rar_yr * 7.0;
  return {
    mwh_yr: Math.round(mwh_yr),
    revenue_yr: Math.round(revenue_yr),
    om_yr: Math.round(om_yr),
    ebitda_yr: Math.round(revenue_yr - om_yr),
    rar_yr: Math.round(rar_yr),
    rar_pct: +(avail_loss * 100).toFixed(2),
    npv_fix: Math.round(npv_fix),
    npv_degrade: Math.round(npv_degrade),
    repair_cost: Math.round(repair_cost),
    pr: +(0.82 - (health_gap * 0.0015)).toFixed(3),   // performance ratio
    soiling_pct_mo: +(0.4 + (100-site.health)*0.02).toFixed(2),
    mic_count: insp.length,
    mic_cost_total: insp.length * FIN.mic_cost_eur,
    roi_ratio: insp.length > 0 ? +(rar_yr / (insp.length * FIN.mic_cost_eur)).toFixed(1) : 0,
  };
}

/* Deterministic month-series per site (12 months back) */
function monthSeriesFor(site, metric) {
  const seed = site.id.split("").reduce((a,c) => a + c.charCodeAt(0), 0);
  const base = { health: site.health, pr: 0.82, soiling: 0.6, detections: 4, availability: 98.5 }[metric] || 50;
  const amp  = { health: 6,           pr: 0.04, soiling: 0.5, detections: 3, availability: 1.5 }[metric] || 5;
  const season = { health: -1, pr: 1, soiling: -1, detections: 1, availability: 1 }[metric] || 1;
  return Array.from({ length: 12 }).map((_, i) => {
    const t = i / 11;
    const wave = Math.sin((t + seed * 0.1) * Math.PI * 2) * season;
    const noise = ((seed * (i+1)) % 13 - 6) / 6;
    return +(base + wave * amp * 0.5 + noise * amp * 0.3).toFixed(2);
  });
}

function fmtEur(n, compact) {
  if (n == null) return "—";
  const abs = Math.abs(n);
  if (compact) {
    if (abs >= 1e6) return `${n < 0 ? "−" : ""}€${(abs/1e6).toFixed(1)}M`;
    if (abs >= 1e3) return `${n < 0 ? "−" : ""}€${(abs/1e3).toFixed(0)}k`;
    return `${n < 0 ? "−" : ""}€${abs.toFixed(0)}`;
  }
  return (n < 0 ? "−€" : "€") + abs.toLocaleString("en", { maximumFractionDigits: 0 });
}

/* ── Asset Manager shell ────────────────────── */
function AssetManagerPage({ go, setActiveSite }) {
  const [tab, setTab] = useStateAM("overview");
  const sites = window.SITES || [];
  const fins = useMemoAM(() => sites.map(s => ({ site: s, fin: computeSiteFin(s) })), [sites]);

  const agg = useMemoAM(() => {
    const total_cap   = fins.reduce((a, x) => a + x.site.capacity_mw, 0);
    const total_mwh   = fins.reduce((a, x) => a + x.fin.mwh_yr, 0);
    const total_rev   = fins.reduce((a, x) => a + x.fin.revenue_yr, 0);
    const total_ebitda= fins.reduce((a, x) => a + x.fin.ebitda_yr, 0);
    const total_rar   = fins.reduce((a, x) => a + x.fin.rar_yr, 0);
    const total_mic   = fins.reduce((a, x) => a + x.fin.mic_cost_total, 0);
    const avg_pr      = fins.reduce((a, x) => a + x.fin.pr, 0) / fins.length;
    const avg_health  = fins.reduce((a, x) => a + x.site.health, 0) / fins.length;
    return { total_cap, total_mwh, total_rev, total_ebitda, total_rar, total_mic, avg_pr, avg_health };
  }, [fins]);

  return (
    <div className="page am-page">
      <div className="page-head">
        <div className="title">
          <div className="kicker">Asset intelligence · Portfolio view</div>
          <h1>Insights</h1>
          <div className="sub">Cross-site trends, peer benchmarks, and financial modelling across {sites.length} assets · {agg.total_cap.toFixed(1)} MW.</div>
        </div>
        <div className="actions">
          <button className="btn btn-secondary btn-md"><Icon name="download" size={12}/>Export pack</button>
          <button className="btn btn-secondary btn-md"><Icon name="calendar" size={12}/>FY26 board review</button>
        </div>
      </div>

      <div className="am-kpi-row">
        <AmKpi lbl="Annual revenue"   val={fmtEur(agg.total_rev, true)}    sub={`${(agg.total_mwh/1e3).toFixed(1)} GWh/yr`}/>
        <AmKpi lbl="EBITDA"           val={fmtEur(agg.total_ebitda, true)} sub={`margin ${((agg.total_ebitda/agg.total_rev)*100).toFixed(0)}%`}/>
        <AmKpi lbl="Revenue at risk"  val={fmtEur(agg.total_rar, true)}    sub={`${((agg.total_rar/agg.total_rev)*100).toFixed(1)}% of rev · ${fins.reduce((a,x) => a + (window.INSPECTIONS||[]).filter(i => i.siteId === x.site.id).reduce((b,i) => b + (i.critical||0), 0), 0)} critical open`} tone="crit"/>
        <AmKpi lbl="Portfolio PR"     val={agg.avg_pr.toFixed(3)}           sub={`target 0.82 · p50 peer`}/>
        <AmKpi lbl="Avg health"       val={`${agg.avg_health.toFixed(1)}`}  sub="out of 100"/>
        <AmKpi lbl="Inspection spend" val={fmtEur(agg.total_mic, true)}     sub={`${fmtEur(agg.total_rar/Math.max(1,agg.total_mic), false)} € recovered / € spent`} tone="pos"/>
      </div>

      <div className="tabs" style={{ marginTop: 18, marginBottom: 16 }}>
        {[["overview","Overview"],["trends","Cross-site trends"],["bench","Benchmarks"],["fin","Financial model"]].map(([v,l]) => (
          <button key={v} className={tab===v?"on":""} onClick={() => setTab(v)}>{l}</button>
        ))}
      </div>

      {tab === "overview" && <AmOverview fins={fins} agg={agg} setActiveSite={setActiveSite} go={go}/>}
      {tab === "trends"   && <AmTrends fins={fins}/>}
      {tab === "bench"    && <AmBenchmarks fins={fins} setActiveSite={setActiveSite} go={go}/>}
      {tab === "fin"      && <AmFinancial fins={fins} agg={agg} setActiveSite={setActiveSite} go={go}/>}
    </div>
  );
}

function AmKpi({ lbl, val, sub, tone }) {
  return (
    <div className={`am-kpi ${tone ? "am-kpi-"+tone : ""}`}>
      <div className="am-kpi-lbl">{lbl}</div>
      <div className="am-kpi-val mono">{val}</div>
      <div className="am-kpi-sub">{sub}</div>
    </div>
  );
}

/* ── Overview: ranking + alerts ─────────────── */
function AmOverview({ fins, agg, setActiveSite, go }) {
  const sorted = [...fins].sort((a,b) => b.fin.rar_yr - a.fin.rar_yr);
  const underperf = [...fins].filter(x => x.site.health < agg.avg_health - 5).sort((a,b) => a.site.health - b.site.health).slice(0, 3);
  const improvers = [...fins].filter(x => x.site.health >= agg.avg_health + 3).slice(0, 3);

  return (
    <div className="am-grid am-grid-overview">
      <div className="card am-card">
        <div className="card-hd">Revenue at risk ranking<span className="sub">top contributors</span></div>
        <div className="am-rank">
          {sorted.slice(0, 6).map(({ site, fin }, i) => {
            const pct = (fin.rar_yr / sorted[0].fin.rar_yr) * 100;
            return (
              <button key={site.id} className="am-rank-row" onClick={() => { setActiveSite(site.id); go("site"); }}>
                <span className="am-rank-n mono">#{i+1}</span>
                <span className="am-rank-name">{site.name}</span>
                <span className="am-rank-bar">
                  <span className="am-rank-bar-fill" style={{ width: `${pct}%` }}/>
                </span>
                <span className="am-rank-val mono num">{fmtEur(fin.rar_yr, true)}</span>
                <span className="am-rank-pct mono sec">{fin.rar_pct}%</span>
              </button>
            );
          })}
        </div>
      </div>

      <div className="card am-card">
        <div className="card-hd">Under-performers<span className="sub">health &lt; portfolio avg</span></div>
        <div className="am-under">
          {underperf.map(({ site, fin }) => (
            <div key={site.id} className="am-under-row" onClick={() => { setActiveSite(site.id); go("site"); }}>
              <Ring pct={site.health}/>
              <div className="am-under-body">
                <div className="am-under-name">{site.name}</div>
                <div className="am-under-sub mono sec">{site.country} · {site.capacity_mw} MW · PR {fin.pr}</div>
              </div>
              <div className="am-under-rar mono">{fmtEur(fin.rar_yr, true)}/yr</div>
            </div>
          ))}
          {underperf.length === 0 && <div style={{ padding: 20, textAlign: "center", color: "var(--fg-muted)", fontSize: 12 }}>All sites within 5 pts of average</div>}
        </div>
      </div>

      <div className="card am-card">
        <div className="card-hd">Improvers<span className="sub">health ≥ avg + 3</span></div>
        <div className="am-under">
          {improvers.map(({ site, fin }) => (
            <div key={site.id} className="am-under-row" onClick={() => { setActiveSite(site.id); go("site"); }}>
              <Ring pct={site.health}/>
              <div className="am-under-body">
                <div className="am-under-name">{site.name}</div>
                <div className="am-under-sub mono sec">{site.country} · PR {fin.pr}</div>
              </div>
              <div style={{ color: "var(--sev-low)", fontSize: 11 }}>↑ best-in-class</div>
            </div>
          ))}
        </div>
      </div>

      <div className="card am-card am-forecast">
        <div className="card-hd">12-month revenue forecast<span className="sub">portfolio total · assuming current degradation</span></div>
        <AmForecastChart agg={agg}/>
      </div>
    </div>
  );
}

function AmForecastChart({ agg }) {
  const base = agg.total_rev / 12;
  const atRisk = agg.total_rar / 12;
  const months = ["May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Jan","Feb","Mar","Apr"];
  const seasonality = [0.95,1.05,1.18,1.22,1.08,0.88,0.72,0.65,0.70,0.85,0.98,1.06];
  const values = months.map((m, i) => ({
    month: m,
    realized: i < 2 ? base * seasonality[i] : null,
    baseline: base * seasonality[i],
    risk: atRisk * seasonality[i],
  }));
  const maxV = Math.max(...values.map(v => v.baseline));
  return (
    <div className="am-forecast-chart">
      <svg viewBox="0 0 700 180" preserveAspectRatio="none" style={{ width: "100%", height: 180 }}>
        {/* gridlines */}
        {[0.25, 0.5, 0.75, 1].map((p, i) => (
          <line key={i} x1="40" x2="690" y1={170 - p*140} y2={170 - p*140} stroke="var(--border-base)" strokeWidth="1" strokeDasharray="2,3"/>
        ))}
        {/* bars */}
        {values.map((v, i) => {
          const x = 50 + i * 53;
          const baseH = (v.baseline / maxV) * 140;
          const riskH = (v.risk / maxV) * 140;
          return (
            <g key={i}>
              <rect x={x} y={170 - baseH} width="36" height={baseH - riskH} fill="var(--accent-primary)" opacity={v.realized ? 1 : 0.55} rx="2"/>
              <rect x={x} y={170 - riskH} width="36" height={riskH} fill="var(--sev-critical)" opacity="0.7"/>
              <text x={x + 18} y="182" textAnchor="middle" fontSize="9" fill="var(--fg-muted)" fontFamily="var(--font-mono)">{v.month}</text>
            </g>
          );
        })}
        <text x="5" y="36" fontSize="9" fill="var(--fg-muted)" fontFamily="var(--font-mono)">{fmtEur(maxV, true)}</text>
        <text x="5" y="172" fontSize="9" fill="var(--fg-muted)" fontFamily="var(--font-mono)">€0</text>
      </svg>
      <div className="am-forecast-legend">
        <span><span className="sq" style={{ background: "var(--accent-primary)" }}/>Baseline realized</span>
        <span><span className="sq" style={{ background: "var(--accent-primary)", opacity: 0.55 }}/>Baseline forecast</span>
        <span><span className="sq" style={{ background: "var(--sev-critical)", opacity: 0.7 }}/>Revenue at risk</span>
      </div>
    </div>
  );
}

/* ── Trends: heatmap sites × months ─────────── */
function AmTrends({ fins }) {
  const [metric, setMetric] = useStateAM("health");
  const months = ["M-11","M-10","M-9","M-8","M-7","M-6","M-5","M-4","M-3","M-2","M-1","M0"];
  const series = fins.map(({ site }) => ({ site, data: monthSeriesFor(site, metric) }));

  const flat = series.flatMap(s => s.data);
  const mn = Math.min(...flat), mx = Math.max(...flat);
  const normalize = (v) => (v - mn) / Math.max(0.0001, mx - mn);

  const metrics = [
    ["health","Site health"],
    ["pr","Performance ratio"],
    ["soiling","Soiling loss %"],
    ["detections","Detections/month"],
    ["availability","Availability %"],
  ];

  return (
    <div className="am-trends">
      <div className="am-toolbar">
        <span className="caps">Metric</span>
        <div className="seg">
          {metrics.map(([v,l]) => <button key={v} className={metric===v?"on":""} onClick={() => setMetric(v)}>{l}</button>)}
        </div>
      </div>

      <div className="card am-card">
        <div className="card-hd">Cross-site heatmap<span className="sub">rows sorted by last value · 12 months</span></div>
        <div className="am-heat">
          <div className="am-heat-hd">
            <div className="am-heat-hd-site">Site</div>
            {months.map(m => <div key={m} className="am-heat-hd-m mono">{m}</div>)}
            <div className="am-heat-hd-cur mono">Now</div>
          </div>
          {series.sort((a,b) => b.data[11] - a.data[11]).map(({ site, data }) => (
            <div key={site.id} className="am-heat-row">
              <div className="am-heat-site">
                <span className="am-heat-name">{site.name}</span>
                <span className="am-heat-sub mono sec">{site.capacity_mw} MW</span>
              </div>
              {data.map((v, i) => {
                const n = normalize(v);
                const color = metric === "detections" || metric === "soiling"
                  ? `color-mix(in oklab, var(--sev-critical) ${Math.round(n*80)}%, var(--bg-inset))`
                  : `color-mix(in oklab, var(--sev-low) ${Math.round(n*80)}%, var(--bg-inset))`;
                return <div key={i} className="am-heat-c" style={{ background: color }} title={`${months[i]}: ${v}`}/>;
              })}
              <div className="am-heat-cur mono num">{data[11].toFixed(1)}</div>
            </div>
          ))}
        </div>
      </div>

      <div className="card am-card">
        <div className="card-hd">Overlay comparison<span className="sub">all sites, same axis</span></div>
        <div className="am-overlay">
          <svg viewBox="0 0 700 220" preserveAspectRatio="none" style={{ width: "100%", height: 220 }}>
            {[0.25,0.5,0.75,1].map((p,i) => (
              <line key={i} x1="30" x2="690" y1={20 + p*180} y2={20 + p*180} stroke="var(--border-base)" strokeWidth="1" strokeDasharray="2,3"/>
            ))}
            {series.map(({ site, data }, si) => {
              const pts = data.map((v, i) => {
                const x = 30 + (i / 11) * 660;
                const y = 200 - ((v - mn) / Math.max(0.0001, mx - mn)) * 180;
                return `${x.toFixed(1)},${y.toFixed(1)}`;
              }).join(" ");
              const hue = (si * 47) % 360;
              return <polyline key={site.id} points={pts} fill="none" stroke={`hsl(${hue}, 65%, 62%)`} strokeWidth="1.8" opacity="0.75"/>;
            })}
          </svg>
          <div className="am-overlay-legend">
            {series.map(({ site }, si) => (
              <span key={site.id} className="am-overlay-it">
                <span className="sq" style={{ background: `hsl(${(si*47)%360}, 65%, 62%)` }}/>
                <span className="sec">{site.name}</span>
              </span>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── Benchmarks ──────────────────────────── */
function AmBenchmarks({ fins, setActiveSite, go }) {
  // Peer groups by type
  const groups = fins.reduce((acc, x) => {
    const key = x.site.type || "Solar";
    (acc[key] = acc[key] || []).push(x);
    return acc;
  }, {});

  return (
    <div className="am-bench">
      {Object.entries(groups).map(([type, items]) => {
        const prs = items.map(x => x.fin.pr).sort((a,b) => a-b);
        const p25 = prs[Math.floor(prs.length*0.25)];
        const p50 = prs[Math.floor(prs.length*0.5)];
        const p75 = prs[Math.floor(prs.length*0.75)];
        const min = prs[0], max = prs[prs.length-1];
        return (
          <div key={type} className="card am-card" style={{ marginBottom: 16 }}>
            <div className="card-hd">{type} peer group<span className="sub">{items.length} sites · PR distribution</span></div>
            <div className="am-box">
              <svg viewBox="0 0 700 60" preserveAspectRatio="none" style={{ width: "100%", height: 60 }}>
                {/* Axis */}
                <line x1="40" x2="660" y1="42" y2="42" stroke="var(--border-base)"/>
                {[0, 0.25, 0.5, 0.75, 1].map((p, i) => {
                  const val = min + (max - min) * p;
                  const x = 40 + p * 620;
                  return (
                    <g key={i}>
                      <line x1={x} x2={x} y1="38" y2="46" stroke="var(--border-base)"/>
                      <text x={x} y="58" fontSize="9" textAnchor="middle" fill="var(--fg-muted)" fontFamily="var(--font-mono)">{val.toFixed(3)}</text>
                    </g>
                  );
                })}
                {/* Box p25-p75 */}
                {(() => {
                  const xmin = 40, xmax = 660, range = max - min || 0.01;
                  const x25 = xmin + ((p25 - min)/range) * (xmax - xmin);
                  const x75 = xmin + ((p75 - min)/range) * (xmax - xmin);
                  const x50 = xmin + ((p50 - min)/range) * (xmax - xmin);
                  return (
                    <>
                      <line x1={xmin} x2={xmax} y1="22" y2="22" stroke="var(--fg-muted)" strokeDasharray="3,3"/>
                      <rect x={x25} y="10" width={x75-x25} height="24" fill="color-mix(in oklab, var(--accent-primary) 18%, transparent)" stroke="var(--accent-primary)" strokeWidth="1.2" rx="2"/>
                      <line x1={x50} x2={x50} y1="10" y2="34" stroke="var(--accent-primary)" strokeWidth="2"/>
                    </>
                  );
                })()}
                {/* Site dots */}
                {items.map(({ site, fin }) => {
                  const x = 40 + ((fin.pr - min) / (max - min || 0.01)) * 620;
                  return <circle key={site.id} cx={x} cy="22" r="4" fill="var(--fg-primary)" stroke="var(--accent-primary)" strokeWidth="1.5"><title>{site.name}: {fin.pr}</title></circle>;
                })}
              </svg>
            </div>

            <table className="tbl am-bench-tbl">
              <thead><tr>
                <th>Site</th><th>PR</th><th>vs. p50</th><th>Health</th><th>Soiling/mo</th><th>RAR/yr</th><th></th>
              </tr></thead>
              <tbody>
                {items.sort((a,b) => b.fin.pr - a.fin.pr).map(({ site, fin }) => {
                  const delta = fin.pr - p50;
                  return (
                    <tr key={site.id} onClick={() => { setActiveSite(site.id); go("site"); }} style={{ cursor: "pointer" }}>
                      <td><b>{site.name}</b> <span className="sec" style={{ fontSize: 10 }}>{site.country}</span></td>
                      <td className="mono num">{fin.pr}</td>
                      <td className="mono num" style={{ color: delta >= 0 ? "var(--sev-low)" : "var(--sev-high)" }}>
                        {delta >= 0 ? "+" : ""}{(delta*100).toFixed(1)}pp
                      </td>
                      <td className="mono num">{site.health}</td>
                      <td className="mono num">{fin.soiling_pct_mo}%</td>
                      <td className="mono num">{fmtEur(fin.rar_yr, true)}</td>
                      <td style={{ textAlign: "right" }}><Icon name="arrow_right" size={12} style={{ color: "var(--fg-muted)" }}/></td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        );
      })}
    </div>
  );
}

/* ── Financial model ─────────────────────── */
function AmFinancial({ fins, agg, setActiveSite, go }) {
  const total_npv_fix = fins.reduce((a,x) => a + x.fin.npv_fix, 0);
  const total_npv_degrade = fins.reduce((a,x) => a + x.fin.npv_degrade, 0);
  const intervene_value = total_npv_fix - total_npv_degrade;
  const total_repair = fins.reduce((a,x) => a + x.fin.repair_cost, 0);

  return (
    <div className="am-fin">
      <div className="am-fin-top">
        <div className="card am-card">
          <div className="card-hd">NPV · Intervene vs. degrade<span className="sub">7-year horizon · 7% discount</span></div>
          <div className="am-npv">
            <div className="am-npv-row">
              <span className="am-npv-lbl">Do nothing (degrade)</span>
              <div className="am-npv-bar neg"><span style={{ width: "100%" }}/></div>
              <span className="mono num" style={{ color: "var(--sev-critical)" }}>{fmtEur(total_npv_degrade, true)}</span>
            </div>
            <div className="am-npv-row">
              <span className="am-npv-lbl">Intervene now</span>
              <div className="am-npv-bar pos"><span style={{ width: `${Math.abs(total_npv_fix / total_npv_degrade) * 100}%` }}/></div>
              <span className="mono num" style={{ color: total_npv_fix >= 0 ? "var(--sev-low)" : "var(--sev-medium)" }}>{fmtEur(total_npv_fix, true)}</span>
            </div>
            <div className="am-npv-sep"/>
            <div className="am-npv-row am-npv-delta">
              <span className="am-npv-lbl"><b>Value of intervention</b></span>
              <span className="grow"/>
              <span className="mono num" style={{ color: "var(--sev-low)", fontSize: 18, fontWeight: 700 }}>{fmtEur(intervene_value, true)}</span>
            </div>
            <div className="am-npv-meta">
              <span className="sec">Up-front cost</span><span className="mono num">{fmtEur(total_repair, true)}</span>
              <span className="sec">Payback</span><span className="mono num">{(total_repair / (agg.total_rar || 1)).toFixed(1)} yr</span>
              <span className="sec">IRR (est.)</span><span className="mono num">{((agg.total_rar / total_repair) * 100).toFixed(1)}%</span>
            </div>
          </div>
        </div>

        <div className="card am-card">
          <div className="card-hd">Inspection ROI<span className="sub">program-wide</span></div>
          <div className="am-roi">
            <div className="am-roi-stat">
              <div className="am-roi-val mono">{fmtEur(agg.total_mic, true)}</div>
              <div className="am-roi-lbl">Inspection spend (LTM)</div>
            </div>
            <div className="am-roi-stat">
              <div className="am-roi-val mono" style={{ color: "var(--sev-low)" }}>{fmtEur(agg.total_rar, true)}</div>
              <div className="am-roi-lbl">Revenue protected (annualized)</div>
            </div>
            <div className="am-roi-stat">
              <div className="am-roi-val mono" style={{ color: "var(--accent-primary)", fontSize: 28 }}>{(agg.total_rar / Math.max(1, agg.total_mic)).toFixed(1)}×</div>
              <div className="am-roi-lbl">Return multiple</div>
            </div>
          </div>
          <div className="am-roi-note">Each € invested in drone inspection protects {(agg.total_rar / Math.max(1, agg.total_mic)).toFixed(1)}€ of annualized revenue exposure. Reference: IEA PVPS Task 13 benchmark 4.2× for solar.</div>
        </div>
      </div>

      <div className="card am-card">
        <div className="card-hd">Per-site financial model<span className="sub">sorted by NPV of intervention</span></div>
        <table className="tbl am-fin-tbl">
          <thead><tr>
            <th>Site</th><th>Capacity</th><th>Revenue/yr</th><th>EBITDA/yr</th><th>RAR/yr</th><th>Repair cost</th><th>NPV (fix)</th><th>NPV (degrade)</th><th>Decision</th><th></th>
          </tr></thead>
          <tbody>
            {[...fins].sort((a,b) => (b.fin.npv_fix - b.fin.npv_degrade) - (a.fin.npv_fix - a.fin.npv_degrade)).map(({ site, fin }) => {
              const valueIntervene = fin.npv_fix - fin.npv_degrade;
              const decision = valueIntervene > fin.repair_cost * 0.5 ? "fix" : valueIntervene > 0 ? "evaluate" : "monitor";
              return (
                <tr key={site.id} onClick={() => { setActiveSite(site.id); go("site"); }} style={{ cursor: "pointer" }}>
                  <td><b>{site.name}</b></td>
                  <td className="mono num">{site.capacity_mw} MW</td>
                  <td className="mono num">{fmtEur(fin.revenue_yr, true)}</td>
                  <td className="mono num">{fmtEur(fin.ebitda_yr, true)}</td>
                  <td className="mono num" style={{ color: fin.rar_pct > 2 ? "var(--sev-critical)" : fin.rar_pct > 1 ? "var(--sev-medium)" : "var(--fg-secondary)" }}>
                    {fmtEur(fin.rar_yr, true)} <span className="sec" style={{ fontSize: 10 }}>({fin.rar_pct}%)</span>
                  </td>
                  <td className="mono num">{fmtEur(fin.repair_cost, true)}</td>
                  <td className="mono num" style={{ color: fin.npv_fix >= 0 ? "var(--sev-low)" : "var(--sev-medium)" }}>{fmtEur(fin.npv_fix, true)}</td>
                  <td className="mono num" style={{ color: "var(--sev-critical)" }}>{fmtEur(fin.npv_degrade, true)}</td>
                  <td>
                    <span className={`am-dec am-dec-${decision}`}>
                      {decision === "fix" ? "Fix now" : decision === "evaluate" ? "Evaluate" : "Monitor"}
                    </span>
                  </td>
                  <td style={{ textAlign: "right" }}><Icon name="arrow_right" size={12} style={{ color: "var(--fg-muted)" }}/></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      <div className="am-fin-note">
        Assumptions: PPA blended €{FIN.price_eur_mwh}/MWh · CF solar {(FIN.cf_solar*100).toFixed(0)}% / wind {(FIN.cf_wind*100).toFixed(0)}% · O&M €{(FIN.om_eur_mw_yr/1000).toFixed(1)}k/MW/yr · discount {(FIN.discount*100).toFixed(0)}% · 7-year horizon. Health→availability factor calibrated against 2024-25 fleet data.
      </div>
    </div>
  );
}

/* ── Per-site Trends tab (exported for Site.jsx) ─── */
function SiteTrendsTab({ site }) {
  const fin = useMemoAM(() => computeSiteFin(site), [site.id]);
  const [metric, setMetric] = useStateAM("health");
  const sites = window.SITES || [];
  const peers = sites.filter(s => s.type === site.type);
  const peerMedian = peers.length > 0 ? [...peers].sort((a,b) => a.health - b.health)[Math.floor(peers.length/2)] : null;
  const best = peers.length > 0 ? [...peers].sort((a,b) => b.health - a.health)[0] : null;

  const selfSeries = monthSeriesFor(site, metric);
  const peerSeries = peerMedian ? monthSeriesFor(peerMedian, metric) : null;
  const bestSeries = best ? monthSeriesFor(best, metric) : null;

  const allVals = [...selfSeries, ...(peerSeries||[]), ...(bestSeries||[])];
  const mn = Math.min(...allVals), mx = Math.max(...allVals);

  const metrics = [
    ["health","Health"],["pr","Performance ratio"],["soiling","Soiling"],["detections","Detections"],["availability","Availability"],
  ];

  return (
    <div className="st">
      <div className="st-kpi-row">
        <AmKpi lbl="Annual revenue"   val={fmtEur(fin.revenue_yr, true)} sub={`${(fin.mwh_yr/1e3).toFixed(1)} GWh/yr`}/>
        <AmKpi lbl="Revenue at risk"  val={fmtEur(fin.rar_yr, true)}     sub={`${fin.rar_pct}% of revenue`} tone={fin.rar_pct > 2 ? "crit" : null}/>
        <AmKpi lbl="Performance ratio" val={fin.pr.toFixed(3)}           sub={peerMedian ? `peer p50 ${(fin.pr - 0.82).toFixed(3) >= 0 ? "above" : "below"}` : "—"}/>
        <AmKpi lbl="NPV if we fix"    val={fmtEur(fin.npv_fix, true)}    sub={`vs ${fmtEur(fin.npv_degrade, true)} if degrade`} tone="pos"/>
      </div>

      <div className="card am-card" style={{ marginBottom: 14 }}>
        <div className="card-hd">
          Trend vs. peers
          <span className="grow"/>
          <div className="seg">
            {metrics.map(([v,l]) => <button key={v} className={metric===v?"on":""} onClick={() => setMetric(v)}>{l}</button>)}
          </div>
        </div>
        <div style={{ padding: 16 }}>
          <svg viewBox="0 0 700 220" preserveAspectRatio="none" style={{ width: "100%", height: 220 }}>
            {[0.25,0.5,0.75,1].map((p,i) => (
              <line key={i} x1="30" x2="690" y1={20 + p*180} y2={20 + p*180} stroke="var(--border-base)" strokeWidth="1" strokeDasharray="2,3"/>
            ))}
            {[
              ["This site", selfSeries, "var(--accent-primary)", 2.5],
              ["Peer p50", peerSeries, "var(--fg-muted)", 1.5],
              ["Best-in-class", bestSeries, "var(--sev-low)", 1.5],
            ].map(([lbl, data, color, w]) => {
              if (!data) return null;
              const pts = data.map((v, i) => {
                const x = 30 + (i / 11) * 660;
                const y = 200 - ((v - mn) / Math.max(0.0001, mx - mn)) * 180;
                return `${x.toFixed(1)},${y.toFixed(1)}`;
              }).join(" ");
              return <polyline key={lbl} points={pts} fill="none" stroke={color} strokeWidth={w} opacity={lbl === "This site" ? 1 : 0.7} strokeDasharray={lbl === "Peer p50" ? "4,3" : undefined}/>;
            })}
          </svg>
          <div className="st-legend">
            <span><span className="sq" style={{ background: "var(--accent-primary)" }}/>This site</span>
            <span><span className="sq" style={{ background: "var(--fg-muted)" }}/>Peer p50</span>
            <span><span className="sq" style={{ background: "var(--sev-low)" }}/>Best-in-class</span>
          </div>
        </div>
      </div>

      <div className="st-fin card am-card">
        <div className="card-hd">Financial snapshot</div>
        <div className="st-fin-body">
          <div className="st-fin-item"><span className="caps">Annual generation</span><span className="mono num">{(fin.mwh_yr/1e3).toFixed(2)} GWh</span></div>
          <div className="st-fin-item"><span className="caps">Revenue</span><span className="mono num">{fmtEur(fin.revenue_yr, true)}</span></div>
          <div className="st-fin-item"><span className="caps">O&amp;M</span><span className="mono num">{fmtEur(-fin.om_yr, true)}</span></div>
          <div className="st-fin-item"><span className="caps">EBITDA</span><span className="mono num" style={{ color: "var(--sev-low)" }}>{fmtEur(fin.ebitda_yr, true)}</span></div>
          <div className="st-fin-item"><span className="caps">Revenue at risk</span><span className="mono num" style={{ color: "var(--sev-critical)" }}>{fmtEur(-fin.rar_yr, true)}/yr</span></div>
          <div className="st-fin-item"><span className="caps">Repair cost (est.)</span><span className="mono num">{fmtEur(fin.repair_cost, true)}</span></div>
          <div className="st-fin-item"><span className="caps">Payback</span><span className="mono num">{(fin.repair_cost / Math.max(1, fin.rar_yr)).toFixed(1)} yr</span></div>
          <div className="st-fin-item"><span className="caps">Inspection ROI</span><span className="mono num" style={{ color: "var(--accent-primary)" }}>{fin.roi_ratio}×</span></div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AssetManagerPage, SiteTrendsTab });
