/* global React, ReactDOM */
const { useState, useMemo, useEffect, useRef } = React;

// ─── Formatting helpers ────────────────────────────────────────────────────
const fmtPLN = n => {
  if (n >= 1_000_000) return (n / 1_000_000).toFixed(2) + ' mln zł';
  if (n >= 10_000) return Math.round(n / 1000) + ' tys. zł';
  if (n >= 1000) return (n / 1000).toFixed(1) + ' tys. zł';
  return Math.round(n) + ' zł';
};
const fmtPLNShort = n => {
  if (n >= 1_000_000) return (n / 1_000_000).toFixed(2) + 'M';
  if (n >= 1000) return (n / 1000).toFixed(0) + 'k';
  return '' + Math.round(n);
};
const fmtInt = n => n.toLocaleString('pl-PL');
const pct = n => Math.round(n * 100) + '%';

const occColor = o => o < 0.40 ? '#52a873' : o < 0.70 ? '#e8b13d' : '#d9533f';

// ─── App ───────────────────────────────────────────────────────────────────
function App() {
  const tweaks = window.useTweaks ? window.useTweaks(window.TWEAK_DEFAULTS) : [window.TWEAK_DEFAULTS, () => {}];
  const [t] = tweaks;

  const [filterCarrier, setFilterCarrier] = useState('ALL');
  const [filterRoute, setFilterRoute] = useState('ALL');
  const [sort, setSort] = useState('revenue');
  const [hoverTrain, setHoverTrain] = useState(null);
  const [selectedTrain, setSelectedTrain] = useState(null);

  const trains = window.TRAINS;

  const filtered = useMemo(() => {
    // Only show trains currently in motion (departed, not yet arrived)
    let ts = trains.filter(x => x.status === 'enroute');
    if (filterCarrier !== 'ALL') ts = ts.filter(x => x.carrier === filterCarrier);
    if (filterRoute !== 'ALL') ts = ts.filter(x => x.route === filterRoute);
    if (sort === 'revenue') ts = [...ts].sort((a, b) => b.revenue - a.revenue);
    else if (sort === 'occupancy') ts = [...ts].sort((a, b) => b.occupancy - a.occupancy);
    else if (sort === 'delay') ts = [...ts].sort((a, b) => b.delayMin - a.delayMin);
    else if (sort === 'dep') ts = [...ts].sort((a, b) => a.depTime.localeCompare(b.depTime));
    return ts;
  }, [trains, filterCarrier, filterRoute, sort]);

  // Totals
  const totals = useMemo(() => {
    const byCarrier = {};
    const byRoute = {};
    let totalRev = 0, totalSeats = 0, totalCap = 0, totalTrains = 0;
    trains.forEach(tr => {
      totalRev += tr.revenue;
      totalSeats += tr.soldSeats;
      totalCap += tr.capacity;
      totalTrains += 1;
      if (!byCarrier[tr.carrier]) byCarrier[tr.carrier] = { revenue: 0, seats: 0, cap: 0, trains: 0 };
      byCarrier[tr.carrier].revenue += tr.revenue;
      byCarrier[tr.carrier].seats += tr.soldSeats;
      byCarrier[tr.carrier].cap += tr.capacity;
      byCarrier[tr.carrier].trains += 1;
      if (!byRoute[tr.route]) byRoute[tr.route] = { revenue: 0, seats: 0, trains: 0, route: tr.route, from: tr.from, to: tr.to };
      byRoute[tr.route].revenue += tr.revenue;
      byRoute[tr.route].seats += tr.soldSeats;
      byRoute[tr.route].trains += 1;
    });
    return { byCarrier, byRoute, totalRev, totalSeats, totalCap, totalTrains };
  }, [trains]);

  const topCarriers = Object.entries(totals.byCarrier)
    .map(([k, v]) => ({ carrier: k, ...v }))
    .sort((a, b) => b.revenue - a.revenue);

  const topRoutes = Object.values(totals.byRoute)
    .sort((a, b) => b.revenue - a.revenue);

  return (
    <div className="app">
      <TopBar totals={totals} />
      <div className="main">
        <aside className="left-rail">
          <CarrierLeaderboard data={topCarriers} totalRev={totals.totalRev}
            filterCarrier={filterCarrier} setFilterCarrier={setFilterCarrier} />
          <RouteLeaderboard data={topRoutes} totalRev={totals.totalRev}
            filterRoute={filterRoute} setFilterRoute={setFilterRoute} />
        </aside>
        <section className="center">
          <MapPanel trains={trains} hoverTrain={hoverTrain}
            setHoverTrain={setHoverTrain} selectedTrain={selectedTrain}
            setSelectedTrain={setSelectedTrain} filterCarrier={filterCarrier}
            filterRoute={filterRoute} showPaths={t.showPaths}
            showCityLabels={t.showCityLabels} showOutline={t.showOutline} />
          <TrainList trains={filtered} sort={sort} setSort={setSort}
            hoverTrain={hoverTrain} setHoverTrain={setHoverTrain}
            selectedTrain={selectedTrain} setSelectedTrain={setSelectedTrain}
            seatGrid={t.seatGrid} compact={t.compact} />
        </section>
      </div>
      <BottomBar totalTrains={totals.totalTrains} filtered={filtered.length} />
      {window.TweaksPanel_App ? <window.TweaksPanel_App /> : null}
    </div>
  );
}

// ─── Top bar ───────────────────────────────────────────────────────────────
function TopBar({ totals }) {
  return (
    <header className="topbar">
      <div className="topbar-brand">
        <div className="brand-mark" />
        <div>
          <div className="brand-title">Gdzie jest złoty pociąg?</div>
          <div className="brand-sub">Polska · {window.TODAY_LABEL} · {window.NOW_LABEL} <span className="live-dot" /> live</div>
        </div>
      </div>
      <div className="topbar-kpis">
        <Kpi label="Przychód dzisiaj" value={fmtPLN(totals.totalRev)} hi />
        <Kpi label="Pasażerowie" value={fmtInt(totals.totalSeats)} />
        <Kpi label="Obłożenie" value={pct(totals.totalSeats / totals.totalCap)} />
        <Kpi label="Pociągi" value={totals.totalTrains} />
      </div>
    </header>
  );
}

function Kpi({ label, value, hi }) {
  return (
    <div className={'kpi' + (hi ? ' kpi-hi' : '')}>
      <div className="kpi-label">{label}</div>
      <div className="kpi-value">{value}</div>
    </div>
  );
}

// ─── Carrier leaderboard ───────────────────────────────────────────────────
function CarrierLeaderboard({ data, totalRev, filterCarrier, setFilterCarrier }) {
  const max = Math.max(...data.map(d => d.revenue));
  return (
    <div className="panel">
      <div className="panel-head">
        <span className="panel-title">Przewoźnicy</span>
        <span className="panel-sub">wg przychodu</span>
      </div>
      <div className="carrier-list">
        <div className={'carrier-row' + (filterCarrier === 'ALL' ? ' active' : '')}
             onClick={() => setFilterCarrier('ALL')}>
          <div className="carrier-swatch" style={{ background: '#444' }} />
          <div className="carrier-name">Wszyscy</div>
          <div className="carrier-rev">{fmtPLN(totalRev)}</div>
        </div>
        {data.map(d => {
          const meta = window.CARRIERS[d.carrier];
          const active = filterCarrier === d.carrier;
          return (
            <div key={d.carrier} className={'carrier-row' + (active ? ' active' : '')}
                 onClick={() => setFilterCarrier(active ? 'ALL' : d.carrier)}>
              <div className="carrier-swatch" style={{ background: meta.color }} />
              <div className="carrier-name">{meta.name}</div>
              <div className="carrier-rev">{fmtPLN(d.revenue)}</div>
              <div className="carrier-bar-wrap">
                <div className="carrier-bar" style={{ width: (d.revenue / max * 100) + '%', background: meta.color }} />
              </div>
              <div className="carrier-meta">
                <span>{d.trains} poc.</span>
                <span>·</span>
                <span>{pct(d.seats / d.cap)}</span>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─── Route leaderboard ─────────────────────────────────────────────────────
function RouteLeaderboard({ data, totalRev, filterRoute, setFilterRoute }) {
  const max = Math.max(...data.map(d => d.revenue));
  return (
    <div className="panel">
      <div className="panel-head">
        <span className="panel-title">Trasy</span>
        <span className="panel-sub">top 10</span>
      </div>
      <div className="route-list">
        {data.slice(0, 10).map(d => {
          const active = filterRoute === d.route;
          return (
            <div key={d.route} className={'route-row' + (active ? ' active' : '')}
                 onClick={() => setFilterRoute(active ? 'ALL' : d.route)}>
              <div className="route-line">
                <span className="city-from">{d.from.replace(' C.', '').replace(' Gł.', '')}</span>
                <span className="route-arrow">→</span>
                <span className="city-to">{d.to.replace(' C.', '').replace(' Gł.', '').replace(' hl.n.', '').replace(' Hbf', '')}</span>
              </div>
              <div className="route-bar-wrap">
                <div className="route-bar" style={{ width: (d.revenue / max * 100) + '%' }} />
              </div>
              <div className="route-meta">
                <span className="route-rev">{fmtPLN(d.revenue)}</span>
                <span className="route-trains">{d.trains} poc.</span>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─── Map panel ─────────────────────────────────────────────────────────────
function MapPanel({ trains, hoverTrain, setHoverTrain, selectedTrain, setSelectedTrain, filterCarrier, filterRoute, showPaths, showCityLabels = true, showOutline = true }) {
  const W = 720, H = 560;
  const padX = 40, padY = 30;

  // Aspect-preserving scale: Poland is ~1.05 wide:tall after lat correction.
  // Fit to whichever is smaller and center the result.
  const innerW = W - padX * 2, innerH = H - padY * 2;
  const polandAspect = 1.05;
  const scaleW = Math.min(innerW, innerH * polandAspect);
  const scaleH = scaleW / polandAspect;
  const offX = (W - scaleW) / 2;
  const offY = (H - scaleH) / 2;
  const toPx = (x, y) => [offX + x * scaleW, offY + y * scaleH];

  // Visible trains
  const visible = trains.filter(tr => {
    if (filterCarrier !== 'ALL' && tr.carrier !== filterCarrier) return false;
    if (filterRoute !== 'ALL' && tr.route !== filterRoute) return false;
    // Only enroute (departed, not yet arrived) — matches PLK live position feed
    return tr.status === 'enroute';
  });

  // Position of each train along its route polyline based on progressPct
  function trainPos(tr) {
    const path = window.ROUTE_PATHS[tr.route];
    if (!path) return null;
    // total length in normalized units
    const segs = [];
    let total = 0;
    for (let i = 0; i < path.length - 1; i++) {
      const [x1, y1] = path[i], [x2, y2] = path[i + 1];
      const d = Math.hypot(x2 - x1, y2 - y1);
      segs.push({ x1, y1, x2, y2, d, cum: total });
      total += d;
    }
    const target = tr.progressPct * total;
    for (const s of segs) {
      if (target <= s.cum + s.d) {
        const k = (target - s.cum) / s.d;
        return toPx(s.x1 + (s.x2 - s.x1) * k, s.y1 + (s.y2 - s.y1) * k);
      }
    }
    const last = segs[segs.length - 1];
    return toPx(last.x2, last.y2);
  }

  return (
    <div className="panel map-panel">
      <div className="panel-head">
        <span className="panel-title">Mapa · live</span>
        <span className="panel-sub">{visible.length} pociągów w ruchu</span>
        <div className="map-legend">
          <span><i className="leg-dot" style={{ background: occColor(0.2) }} /> &lt;40%</span>
          <span><i className="leg-dot" style={{ background: occColor(0.55) }} /> 40–70%</span>
          <span><i className="leg-dot" style={{ background: occColor(0.85) }} /> &gt;70%</span>
        </div>
      </div>
      <svg className="map-svg" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet">
        {/* Poland outline (stylized) */}
        {showOutline && <PolandOutline toPx={toPx} W={W} H={H} padX={padX} padY={padY} />}

        {/* Route paths */}
        {showPaths && Object.entries(window.ROUTE_PATHS).map(([id, path]) => {
          const active = filterRoute === 'ALL' || filterRoute === id;
          const d = path.map((p, i) => (i === 0 ? 'M' : 'L') + toPx(p[0], p[1]).join(' ')).join(' ');
          return <path key={id} d={d} fill="none"
            stroke={active ? 'rgba(224,17,95,0.22)' : 'rgba(120,120,130,0.08)'}
            strokeWidth={active ? 1.5 : 1}
            strokeDasharray="3 3" />;
        })}

        {/* City labels + dots */}
        {Object.entries(window.CITIES).map(([name, c]) => {
          const [x, y] = toPx(c.x, c.y);
          return (
            <g key={name}>
              <circle cx={x} cy={y} r={c.offMap ? 3 : 4}
                fill={c.offMap ? '#3a3a44' : '#e7e5df'}
                stroke={c.offMap ? '#555' : '#0f1114'}
                strokeWidth="2" />
              {showCityLabels && (
                <text x={x + 8} y={y + 4} className={'city-label' + (c.offMap ? ' off' : '')}>
                  {c.label}
                </text>
              )}
            </g>
          );
        })}

        {/* Train markers */}
        {visible.map(tr => {
          const pos = trainPos(tr);
          if (!pos) return null;
          const [x, y] = pos;
          const meta = window.CARRIERS[tr.carrier];
          const isHover = hoverTrain === tr.id;
          const isSel = selectedTrain === tr.id;
          const revNorm = Math.min(1, tr.revenue / 60000);
          const r = 5 + revNorm * 9;
          return (
            <g key={tr.id}
               className="train-marker"
               onMouseEnter={() => setHoverTrain(tr.id)}
               onMouseLeave={() => setHoverTrain(null)}
               onClick={() => setSelectedTrain(isSel ? null : tr.id)}>
              {(isHover || isSel) && (
                <circle cx={x} cy={y} r={r + 8} fill="none" stroke={meta.color} strokeOpacity="0.35" strokeWidth="2" />
              )}
              <circle cx={x} cy={y} r={r} fill={meta.color} fillOpacity="0.18"
                stroke={meta.color} strokeWidth="1.5" />
              <circle cx={x} cy={y} r={3} fill={occColor(tr.occupancy)} />
              {tr.delayMin >= 10 && (
                <circle cx={x + r + 2} cy={y - r - 2} r="3" fill="#d9533f" stroke="#0f1114" strokeWidth="1" />
              )}
            </g>
          );
        })}
      </svg>

      {/* Tooltip */}
      {hoverTrain && (() => {
        const tr = trains.find(t => t.id === hoverTrain);
        if (!tr) return null;
        return <TrainTooltip train={tr} />;
      })()}
    </div>
  );
}

function PolandOutline({ toPx, W, H, padX, padY }) {
  const pts = window.POLAND_BORDER;
  const d = pts.map((p, i) => (i === 0 ? 'M' : 'L') + toPx(p[0], p[1]).join(' ')).join(' ') + ' Z';
  return (
    <g>
      {/* Subtle grid */}
      {[0.2, 0.4, 0.6, 0.8].map(g => (
        <line key={'gx' + g} x1={padX + g * (W - padX * 2)} y1={padY}
          x2={padX + g * (W - padX * 2)} y2={H - padY}
          stroke="rgba(255,255,255,0.03)" strokeWidth="1" />
      ))}
      {[0.25, 0.5, 0.75].map(g => (
        <line key={'gy' + g} x1={padX} y1={padY + g * (H - padY * 2)}
          x2={W - padX} y2={padY + g * (H - padY * 2)}
          stroke="rgba(255,255,255,0.03)" strokeWidth="1" />
      ))}
      <path d={d} fill="rgba(224,17,95,0.07)" stroke="rgba(224,17,95,0.85)" strokeWidth="1.8" strokeLinejoin="round" />
    </g>
  );
}

function TrainTooltip({ train }) {
  const meta = window.CARRIERS[train.carrier];
  return (
    <div className="map-tooltip">
      <div className="tt-head">
        <span className="tt-swatch" style={{ background: meta.color }} />
        <span className="tt-id">{train.id}</span>
        <span className="tt-time">{train.depTime} → {train.arrTime}</span>
      </div>
      <div className="tt-route">{train.from.replace(' Gł.','').replace(' C.','')} → {train.to.replace(' Gł.','').replace(' C.','').replace(' hl.n.','').replace(' Hbf','')}</div>
      <div className="tt-grid">
        <div><div className="tt-l">Przychód</div><div className="tt-v hi">{fmtPLN(train.revenue)}</div></div>
        <div><div className="tt-l">Obłożenie</div><div className="tt-v" style={{ color: occColor(train.occupancy) }}>{pct(train.occupancy)} · {train.soldSeats}/{train.capacity}</div></div>
        <div><div className="tt-l">Śr. cena</div><div className="tt-v">{train.avgPrice} zł</div></div>
        <div><div className="tt-l">Opóźn.</div><div className="tt-v" style={{ color: train.delayMin >= 5 ? '#d9533f' : '#6b6b72' }}>{train.delayMin > 0 ? '+' + train.delayMin + ' min' : 'punktualnie'}</div></div>
      </div>
    </div>
  );
}

// ─── Train list ────────────────────────────────────────────────────────────
function TrainList({ trains, sort, setSort, hoverTrain, setHoverTrain, selectedTrain, setSelectedTrain, seatGrid, compact }) {
  const maxRev = Math.max(...trains.map(t => t.revenue), 1);
  return (
    <div className={'panel train-list' + (compact ? ' compact' : '')}>
      <div className="panel-head">
        <span className="panel-title">Pociągi</span>
        <span className="panel-sub">{trains.length} w ruchu</span>
        <div className="sort-tabs">
          <button className="on">Przychód</button>
        </div>
      </div>
      <div className="train-scroll">
        {trains.slice(0, 80).map(tr => (
          <TrainRow key={tr.id} train={tr} maxRev={maxRev}
            hover={hoverTrain === tr.id} selected={selectedTrain === tr.id}
            onHover={setHoverTrain} onSelect={setSelectedTrain} seatGrid={seatGrid} />
        ))}
      </div>
    </div>
  );
}

function TrainRow({ train, maxRev, hover, selected, onHover, onSelect, seatGrid }) {
  const meta = window.CARRIERS[train.carrier];
  const barPct = (train.revenue / maxRev) * 100;
  // Build a seat grid: soldSeats filled, empty seats as hollow pixels. Cap display at 200 cells.
  const cells = Math.min(train.capacity, 200);
  const filledRatio = train.soldSeats / train.capacity;
  const filled = Math.round(cells * filledRatio);

  return (
    <div className={'train-row' + (hover ? ' hover' : '') + (selected ? ' selected' : '')}
         onMouseEnter={() => onHover(train.id)}
         onMouseLeave={() => onHover(null)}
         onClick={() => onSelect(selected ? null : train.id)}>
      <div className="tr-col-id">
        <div className="tr-carrier">
          <span className="tr-swatch" style={{ background: meta.color }} />
          {train.id}
        </div>
        <div className="tr-time">
          {train.depTime}
          {train.delayMin > 0 && <span className="tr-delay">+{train.delayMin}</span>}
        </div>
      </div>
      <div className="tr-col-route">
        <div className="tr-route">
          {train.from.replace(' Gł.','').replace(' C.','')} <span className="tr-arrow">→</span> {train.to.replace(' Gł.','').replace(' C.','').replace(' hl.n.','').replace(' Hbf','')}
        </div>
        <div className="tr-meta">
          {train.km} km · {Math.floor(train.travelMin/60)}h {train.travelMin%60}m · {train.avgPrice} zł/bilet
        </div>
      </div>
      {seatGrid && (
        <div className="tr-col-seats">
          <div className="seat-grid">
            {Array.from({ length: cells }).map((_, i) => (
              <span key={i} className={'seat' + (i < filled ? ' filled' : '')}
                style={i < filled ? { background: occColor(train.occupancy) } : null} />
            ))}
          </div>
          <div className="seat-meta">{train.soldSeats}/{train.capacity}</div>
        </div>
      )}
      <div className="tr-col-occ">
        <div className="occ-ring" style={{
          background: `conic-gradient(${occColor(train.occupancy)} ${train.occupancy * 360}deg, #24242a 0)`
        }}>
          <div className="occ-ring-hole">{Math.round(train.occupancy * 100)}</div>
        </div>
      </div>
      <div className="tr-col-rev">
        <div className="tr-rev-val">{fmtPLN(train.revenue)}</div>
        <div className="tr-rev-bar-wrap">
          <div className="tr-rev-bar" style={{ width: barPct + '%', background: meta.color }} />
        </div>
      </div>
    </div>
  );
}

// ─── Bottom bar ────────────────────────────────────────────────────────────
function BottomBar({ totalTrains, filtered }) {
  return (
    <footer className="bottombar">
      <span>źródła: koleo · regiojet · leoexpress · plk · pkp ic</span>
      <span className="sep">·</span>
      <span>{filtered} / {totalTrains} pociągów</span>
      <span className="sep">·</span>
      <span>odświeżono {window.NOW_LABEL}</span>
      <span className="sep">·</span>
      <span>cennik i obłożenie: live z API przewoźników</span>
    </footer>
  );
}

// Expose
window.App = App;
