import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp } from 'lucide-react'
import { Fragment, useEffect, useMemo, useState } from 'react'

import { EnergyFlowSankey, type FlowTotals } from '../components/EnergyFlowSankey'
import { useEnergyFlowsDaily, useEnergyFlowsIntervals } from '../hooks/useEnergyFlows'
import { useSiteStatus } from '../hooks/useSiteStatus'
import { pragueCalendarDay } from '../lib/pragueDate'
import type { DailyEnergyFlows } from '../types/energy-flows'

function currentMonth(): string {
  return pragueCalendarDay().slice(0, 7)
}

function monthLabel(ym: string): string {
  const [y, m] = ym.split('-').map(Number)
  const names = [
    'Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen',
    'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec',
  ]
  return `${names[m - 1]} ${y}`
}

function shiftMonth(ym: string, delta: number): string {
  const [y, m] = ym.split('-').map(Number)
  const d = new Date(y, m - 1 + delta, 1)
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`
}

function fmtDay(iso: string): string {
  const d = new Date(iso + 'T00:00:00')
  return d.toLocaleDateString('cs-CZ', { weekday: 'short', day: 'numeric', month: 'numeric' })
}

function fmtTime(iso: string): string {
  const d = new Date(iso)
  return d.toLocaleTimeString('cs-CZ', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Prague' })
}

function kwh(v: number | null | undefined, d = 2): string {
  if (v == null) return '–'
  return v.toFixed(d)
}

function czk(v: number | null | undefined): string {
  if (v == null) return '–'
  return v.toLocaleString('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}

function aggregateFlows(days: DailyEnergyFlows[]): FlowTotals & {
  pv_production_kwh: number
  grid_import_kwh: number
  grid_export_kwh: number
  batt_charge_kwh: number
  batt_discharge_kwh: number
  load_kwh: number
  grid_import_cashflow_czk: number
  grid_export_revenue_czk: number
  grid_to_load_cost_czk: number
  grid_to_batt_cost_czk: number
} {
  const z = {
    pv_production_kwh: 0,
    grid_import_kwh: 0,
    grid_export_kwh: 0,
    batt_charge_kwh: 0,
    batt_discharge_kwh: 0,
    load_kwh: 0,
    pv_to_load_kwh: 0,
    pv_to_batt_kwh: 0,
    pv_to_grid_kwh: 0,
    batt_to_load_kwh: 0,
    batt_to_grid_kwh: 0,
    grid_to_load_kwh: 0,
    grid_to_batt_kwh: 0,
    grid_import_cashflow_czk: 0,
    grid_export_revenue_czk: 0,
    grid_to_load_cost_czk: 0,
    grid_to_batt_cost_czk: 0,
  }
  for (const d of days) {
    z.pv_production_kwh += d.pv_production_kwh
    z.grid_import_kwh += d.grid_import_kwh
    z.grid_export_kwh += d.grid_export_kwh
    z.batt_charge_kwh += d.batt_charge_kwh
    z.batt_discharge_kwh += d.batt_discharge_kwh
    z.load_kwh += d.load_kwh
    z.pv_to_load_kwh += d.pv_to_load_kwh
    z.pv_to_batt_kwh += d.pv_to_batt_kwh
    z.pv_to_grid_kwh += d.pv_to_grid_kwh
    z.batt_to_load_kwh += d.batt_to_load_kwh
    z.batt_to_grid_kwh += d.batt_to_grid_kwh
    z.grid_to_load_kwh += d.grid_to_load_kwh
    z.grid_to_batt_kwh += d.grid_to_batt_kwh
    z.grid_import_cashflow_czk += d.grid_import_cashflow_czk ?? 0
    z.grid_export_revenue_czk += d.grid_export_revenue_czk ?? 0
    z.grid_to_load_cost_czk += d.grid_to_load_cost_czk ?? 0
    z.grid_to_batt_cost_czk += d.grid_to_batt_cost_czk ?? 0
  }
  return z
}

function IntervalDetail({ siteId, day }: { siteId: number; day: string }) {
  const { intervals, loading } = useEnergyFlowsIntervals(siteId, day)

  if (loading) {
    return <div className="py-3 text-center text-xs text-slate-500">Načítání intervalů…</div>
  }
  if (intervals.length === 0) {
    return <div className="py-3 text-center text-xs text-slate-500">Žádné intervaly</div>
  }

  return (
    <div className="overflow-x-auto">
      <table className="w-full text-xs">
        <thead>
          <tr className="border-b border-slate-700 text-slate-400">
            <th className="px-2 py-1 text-left">Čas</th>
            <th className="px-2 py-1 text-right">PV→Load</th>
            <th className="px-2 py-1 text-right">PV→Batt</th>
            <th className="px-2 py-1 text-right">PV→Grid</th>
            <th className="px-2 py-1 text-right">Batt→Load</th>
            <th className="px-2 py-1 text-right">Batt→Grid</th>
            <th className="px-2 py-1 text-right">Grid→Load</th>
            <th className="px-2 py-1 text-right">Grid→Batt</th>
          </tr>
        </thead>
        <tbody>
          {intervals.map((iv) => (
            <tr key={iv.interval_start} className="border-b border-slate-800 hover:bg-slate-800/40">
              <td className="px-2 py-1 text-slate-300">{fmtTime(iv.interval_start)}</td>
              <td className="px-2 py-1 text-right">{kwh(iv.pv_to_load_kwh)}</td>
              <td className="px-2 py-1 text-right">{kwh(iv.pv_to_batt_kwh)}</td>
              <td className="px-2 py-1 text-right">{kwh(iv.pv_to_grid_kwh)}</td>
              <td className="px-2 py-1 text-right">{kwh(iv.batt_to_load_kwh)}</td>
              <td className="px-2 py-1 text-right">{kwh(iv.batt_to_grid_kwh)}</td>
              <td className="px-2 py-1 text-right">{kwh(iv.grid_to_load_kwh)}</td>
              <td className="px-2 py-1 text-right">{kwh(iv.grid_to_batt_kwh)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

export default function EnergyFlows() {
  const { site: siteRow, ready: siteReady, error: siteError } = useSiteStatus()
  const siteId = siteRow?.site_id ?? null

  const [month, setMonth] = useState(currentMonth)
  const [expandedDay, setExpandedDay] = useState<string | null>(null)
  /** null = součet za celý měsíc; jinak ISO den pro Sankey + perspektivní karty */
  const [scopeDay, setScopeDay] = useState<string | null>(null)

  const { days, loading, error, reload } = useEnergyFlowsDaily(siteId, month)

  useEffect(() => {
    setScopeDay(null)
  }, [month])

  const totals = useMemo(() => {
    if (days.length === 0) return null
    if (scopeDay) {
      const row = days.find((d) => d.day === scopeDay)
      if (row) return aggregateFlows([row])
    }
    return aggregateFlows(days)
  }, [days, scopeDay])

  const flowOnly: FlowTotals | null = totals
    ? {
        pv_to_load_kwh: totals.pv_to_load_kwh,
        pv_to_batt_kwh: totals.pv_to_batt_kwh,
        pv_to_grid_kwh: totals.pv_to_grid_kwh,
        batt_to_load_kwh: totals.batt_to_load_kwh,
        batt_to_grid_kwh: totals.batt_to_grid_kwh,
        grid_to_load_kwh: totals.grid_to_load_kwh,
        grid_to_batt_kwh: totals.grid_to_batt_kwh,
      }
    : null

  const battEff =
    totals && totals.batt_charge_kwh > 0.01
      ? Math.min(100, (totals.batt_discharge_kwh / totals.batt_charge_kwh) * 100)
      : null

  const avgImportKcPerKwh =
    totals && totals.grid_import_kwh > 0.001
      ? totals.grid_import_cashflow_czk / totals.grid_import_kwh
      : null
  const avgExportKcPerKwh =
    totals && totals.grid_export_kwh > 0.001
      ? totals.grid_export_revenue_czk / totals.grid_export_kwh
      : null
  const gridNetCzk =
    totals != null ? totals.grid_import_cashflow_czk - totals.grid_export_revenue_czk : null

  return (
    <main className="mx-auto max-w-7xl space-y-6 px-4 py-6 md:px-8">
      {siteReady && siteRow && (
        <p className="text-xs text-slate-500">
          Lokalita: <span className="text-slate-400">{siteRow.site_code}</span> — toky jsou{' '}
          <strong className="text-slate-400">modelované</strong> prioritní alokací z minutové telemetrie (
          <code className="rounded bg-slate-800 px-1">fn_fill_audit_interval</code>), ne přímé měření větví.
        </p>
      )}
      {siteError && (
        <div className="rounded-lg border border-amber-900/50 bg-amber-950/30 px-3 py-2 text-sm text-amber-200">
          {siteError}
        </div>
      )}

      <div className="flex items-center gap-4">
        <button
          type="button"
          onClick={() => setMonth((m) => shiftMonth(m, -1))}
          className="rounded-lg p-2 text-slate-400 transition hover:bg-slate-800 hover:text-white"
        >
          <ChevronLeft size={20} />
        </button>
        <h1 className="min-w-[200px] text-center text-lg font-semibold text-white">
          Toky energie — {monthLabel(month)}
        </h1>
        <button
          type="button"
          onClick={() => setMonth((m) => shiftMonth(m, 1))}
          className="rounded-lg p-2 text-slate-400 transition hover:bg-slate-800 hover:text-white"
        >
          <ChevronRight size={20} />
        </button>
      </div>

      {!siteReady ? (
        <div className="py-12 text-center text-sm text-slate-500">Načítání lokality…</div>
      ) : siteId == null ? (
        <div className="py-12 text-center text-sm text-slate-500">Vyberte lokalitu v horní liště.</div>
      ) : loading ? (
        <div className="py-12 text-center text-sm text-slate-500">Načítání…</div>
      ) : error ? (
        <div className="rounded-lg border border-red-900/50 bg-red-950/30 px-4 py-3 text-sm text-red-300">
          {error}
        </div>
      ) : (
        <>
          {days.length > 0 && (
            <div className="flex flex-wrap items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/60 px-3 py-2">
              <label htmlFor="energy-flow-scope" className="text-sm text-slate-400">
                Graf a karty:
              </label>
              <select
                id="energy-flow-scope"
                className="max-w-[min(100%,20rem)] rounded-lg border border-slate-700 bg-slate-900 px-3 py-1.5 text-sm text-slate-200"
                value={scopeDay ?? ''}
                onChange={(e) => {
                  const v = e.target.value
                  setScopeDay(v === '' ? null : v)
                }}
              >
                <option value="">Celý měsíc (součet)</option>
                {days.map((d) => (
                  <option key={d.day} value={d.day}>
                    {fmtDay(d.day)}
                  </option>
                ))}
              </select>
            </div>
          )}

          {totals && (
            <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-5">
              <div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
                <p className="text-xs font-medium uppercase tracking-wide text-amber-400">Perspektiva FVE</p>
                <p className="mt-2 text-2xl font-semibold text-white">{totals.pv_production_kwh.toFixed(1)} kWh</p>
                <ul className="mt-2 space-y-1 text-xs text-slate-400">
                  <li>→ spotřeba: {totals.pv_to_load_kwh.toFixed(2)} kWh</li>
                  <li>→ baterie: {totals.pv_to_batt_kwh.toFixed(2)} kWh</li>
                  <li>→ síť (export): {totals.pv_to_grid_kwh.toFixed(2)} kWh</li>
                </ul>
              </div>
              <div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
                <p className="text-xs font-medium uppercase tracking-wide text-sky-400">Perspektiva síť</p>
                <p className="mt-2 text-sm text-slate-400">
                  Import: <span className="font-semibold text-red-300">{totals.grid_import_kwh.toFixed(2)}</span> kWh
                  {' · '}
                  Export:{' '}
                  <span className="font-semibold text-green-300">{totals.grid_export_kwh.toFixed(2)}</span> kWh
                </p>
                <ul className="mt-2 space-y-1 text-xs text-slate-400">
                  <li>Import → spotřeba: {totals.grid_to_load_kwh.toFixed(2)} kWh</li>
                  <li>Import → baterie: {totals.grid_to_batt_kwh.toFixed(2)} kWh</li>
                </ul>
              </div>
              <div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
                <p className="text-xs font-medium uppercase tracking-wide text-emerald-400">Perspektiva baterie</p>
                <p className="mt-2 text-sm text-slate-400">
                  Nabito: <span className="text-white">{totals.batt_charge_kwh.toFixed(2)}</span> kWh · Vybito:{' '}
                  <span className="text-white">{totals.batt_discharge_kwh.toFixed(2)}</span> kWh
                </p>
                <ul className="mt-2 space-y-1 text-xs text-slate-400">
                  <li>Z FVE: {totals.pv_to_batt_kwh.toFixed(2)} kWh · Ze sítě: {totals.grid_to_batt_kwh.toFixed(2)} kWh</li>
                  <li>Do spotřeby: {totals.batt_to_load_kwh.toFixed(2)} kWh · Do sítě: {totals.batt_to_grid_kwh.toFixed(2)} kWh</li>
                  {battEff != null && (
                    <li className="text-slate-500">Poměr vybití/nabití: {battEff.toFixed(0)} % (zjednodušeně)</li>
                  )}
                </ul>
              </div>
              <div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
                <p className="text-xs font-medium uppercase tracking-wide text-violet-400">Perspektiva spotřeby</p>
                <p className="mt-2 text-2xl font-semibold text-white">{totals.load_kwh.toFixed(1)} kWh</p>
                <p className="mt-1 text-xs text-slate-500">Celkový odběr (model z telemetrie)</p>
                <ul className="mt-2 space-y-1 text-xs text-slate-400">
                  <li>
                    Z FVE: <span className="text-amber-200/90">{totals.pv_to_load_kwh.toFixed(2)}</span> kWh
                  </li>
                  <li>
                    Z baterie: <span className="text-emerald-200/90">{totals.batt_to_load_kwh.toFixed(2)}</span> kWh
                  </li>
                  <li>
                    Ze sítě (import): <span className="text-sky-200/90">{totals.grid_to_load_kwh.toFixed(2)}</span> kWh
                  </li>
                </ul>
                <p className="mt-2 border-t border-slate-800 pt-2 text-[11px] leading-snug text-slate-500">
                  Součet tří toků odpovídá modelu prioritní alokace; může se mírně lišit od sloupce „Spotřeba“ kvůli
                  zaokrouhlení po 15min intervalech.
                </p>
              </div>
              <div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
                <p className="text-xs font-medium uppercase tracking-wide text-rose-400">Perspektiva financí</p>
                <p className="mt-2 text-sm text-slate-400">
                  Nákup ze sítě:{' '}
                  <span className="font-semibold text-red-200">{czk(totals.grid_import_cashflow_czk)}</span> Kč
                </p>
                <p className="mt-1 text-sm text-slate-400">
                  Prodej do sítě:{' '}
                  <span className="font-semibold text-green-200">{czk(totals.grid_export_revenue_czk)}</span> Kč
                </p>
                <p className="mt-1 text-sm text-slate-300">
                  Bilance sítě (nákup − prodej):{' '}
                  <span className="font-semibold text-white">{czk(gridNetCzk)}</span> Kč
                </p>
                <ul className="mt-2 space-y-1 border-t border-slate-800 pt-2 text-xs text-slate-400">
                  <li>
                    Prům. cena nákupu:{' '}
                    {avgImportKcPerKwh != null ? (
                      <span className="text-rose-200/90">{avgImportKcPerKwh.toFixed(3)} Kč/kWh</span>
                    ) : (
                      <span>–</span>
                    )}
                  </li>
                  <li>
                    Prům. cena prodeje:{' '}
                    {avgExportKcPerKwh != null ? (
                      <span className="text-emerald-200/90">{avgExportKcPerKwh.toFixed(3)} Kč/kWh</span>
                    ) : (
                      <span>–</span>
                    )}
                  </li>
                </ul>
                <p className="mt-2 text-[11px] font-medium uppercase tracking-wide text-slate-500">
                  Rozpad nákladů importu (efektivní cena × modelovaný tok)
                </p>
                <ul className="mt-1 space-y-1 text-xs text-slate-400">
                  <li>Do spotřeby: {czk(totals.grid_to_load_cost_czk)} Kč</li>
                  <li>Do baterie: {czk(totals.grid_to_batt_cost_czk)} Kč</li>
                </ul>
                <p className="mt-2 border-t border-slate-800 pt-2 text-[11px] leading-snug text-slate-500">
                  Stejná jednotková cena v každém 15min slotu; součet rozpadu se může mírně lišit od celkového nákupu kvůli
                  zaokrouhlení a odchylce modelu toků od měřeného importu.
                </p>
              </div>
            </div>
          )}

          <div className="rounded-xl border border-slate-800 bg-slate-900 p-4">
            <h2 className="mb-2 text-sm font-medium text-slate-300">
              Sankey — {scopeDay ? fmtDay(scopeDay) : 'celý měsíc (součet)'}
            </h2>
            <EnergyFlowSankey totals={flowOnly} />
          </div>

          <div className="overflow-hidden rounded-xl border border-slate-800 bg-slate-900">
            <div className="border-b border-slate-800 px-4 py-3">
              <h2 className="text-sm font-medium text-slate-300">Denní přehled</h2>
            </div>
            {days.length === 0 ? (
              <div className="px-4 py-10 text-center text-sm text-slate-500">
                Žádná data — zkuste jiný měsíc nebo backfill auditu (
                <code className="rounded bg-slate-800 px-1">fn_fill_audit_range</code>).
              </div>
            ) : (
              <div className="overflow-x-auto">
                <table className="w-full">
                  <thead>
                    <tr className="border-b border-slate-700 text-xs text-slate-400">
                      <th className="px-3 py-2 text-left">Den</th>
                      <th className="px-3 py-2 text-right">PV kWh</th>
                      <th className="px-3 py-2 text-right">Import</th>
                      <th className="px-3 py-2 text-right">Export</th>
                      <th className="px-3 py-2 text-right">Nabití</th>
                      <th className="px-3 py-2 text-right">Vybití</th>
                      <th className="px-3 py-2 text-right">Spotřeba</th>
                    </tr>
                  </thead>
                  <tbody>
                    {days.map((row) => (
                      <Fragment key={row.day}>
                        <tr
                          className="cursor-pointer border-b border-slate-800 hover:bg-slate-800/50"
                          onClick={() => setExpandedDay((p) => (p === row.day ? null : row.day))}
                        >
                          <td className="px-3 py-2 text-sm text-slate-200">
                            <span className="mr-1 inline-block w-4">
                              {expandedDay === row.day ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
                            </span>
                            <button
                              type="button"
                              className={`rounded px-1 text-left underline-offset-2 hover:underline ${
                                scopeDay === row.day ? 'text-amber-300' : ''
                              }`}
                              title="Zobrazit tento den v Sankey a ve všech kartách"
                              onClick={(e) => {
                                e.stopPropagation()
                                setScopeDay(row.day)
                              }}
                            >
                              {fmtDay(row.day)}
                            </button>
                          </td>
                          <td className="px-3 py-2 text-right text-sm">{row.pv_production_kwh.toFixed(1)}</td>
                          <td className="px-3 py-2 text-right text-sm">{row.grid_import_kwh.toFixed(2)}</td>
                          <td className="px-3 py-2 text-right text-sm">{row.grid_export_kwh.toFixed(2)}</td>
                          <td className="px-3 py-2 text-right text-sm">{row.batt_charge_kwh.toFixed(2)}</td>
                          <td className="px-3 py-2 text-right text-sm">{row.batt_discharge_kwh.toFixed(2)}</td>
                          <td className="px-3 py-2 text-right text-sm">{row.load_kwh.toFixed(1)}</td>
                        </tr>
                        {expandedDay === row.day && siteId != null ? (
                          <tr>
                            <td colSpan={7} className="bg-slate-900/50 px-4 py-2">
                              <IntervalDetail siteId={siteId} day={row.day} />
                            </td>
                          </tr>
                        ) : null}
                      </Fragment>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>

          <p className="text-center text-xs text-slate-600">
            <button
              type="button"
              className="underline hover:text-slate-400"
              onClick={() => void reload()}
            >
              Znovu načíst
            </button>
          </p>
        </>
      )}
    </main>
  )
}
