import type { ChartArea } from 'chart.js'
import { Activity, Battery, ChevronDown, ChevronUp, Sun, Zap } from 'lucide-react'
import { memo, useCallback, useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'

import { EnergyChart } from '../components/charts/EnergyChart'
import { ForecastPanel } from '../components/charts/ForecastPanel'
import { NegPricePanel } from '../components/charts/NegPricePanel'
import { RegimeBar } from '../components/charts/RegimeBar'
import { SocTuvChart } from '../components/charts/SocTuvChart'
import {
  postImportSitePrices,
  postRunPlan,
  postSiteMode,
} from '../api/backend'
import { CHART_LAYOUT_PADDING } from '../components/charts/chartConstants'
import { ControlPanel } from '../components/ControlPanel'
import { ModeBar } from '../components/ModeBar'
import { NotificationBar } from '../components/NotificationBar'
import { StatePanel } from '../components/StatePanel'
import { PoolCard } from '../components/PoolCard'
import { useDashboardData } from '../hooks/useDashboardData'
import { useFullStatus } from '../hooks/useFullStatus'
import { useNotifications } from '../hooks/useNotifications'
import { useRollingReplanMinutes } from '../hooks/useRollingReplanMinutes'
import { useSiteStatus } from '../hooks/useSiteStatus'

const MemoEnergyChart = memo(EnergyChart, (prev, next) =>
  prev.slots === next.slots && prev.nowIndex === next.nowIndex && prev.hidden === next.hidden,
)

const MemoRegimeBar = memo(RegimeBar, (prev, next) =>
  prev.slots === next.slots &&
  prev.nowIndex === next.nowIndex &&
  prev.chartArea === next.chartArea,
)

const MemoSocTuvChart = memo(SocTuvChart, (prev, next) =>
  prev.slots === next.slots &&
  prev.nowIndex === next.nowIndex &&
  prev.liveBatSoc === next.liveBatSoc,
)

function fmtKw2(w: number | null | undefined): string {
  if (w == null || Number.isNaN(w)) return '—'
  return `${(w / 1000).toFixed(2)} kW`
}

function fmtMoney3(v: number | null | undefined): string {
  if (v == null || Number.isNaN(v)) return '—'
  return `${v.toLocaleString('cs-CZ', { minimumFractionDigits: 3, maximumFractionDigits: 3 })} Kč/kWh`
}

function fmtSoc(p: number | null | undefined): string {
  if (p == null || Number.isNaN(p)) return '—'
  return `${p.toFixed(0)} %`
}

function MetricSkeleton() {
  return <div className="h-[92px] animate-pulse rounded-xl border border-slate-800 bg-slate-900/40" />
}

export function Dashboard() {
  const navigate = useNavigate()
  const { site: siteRow, ready: siteReady, error: siteErr } = useSiteStatus()
  const siteId = siteRow?.site_id ?? null
  const data = useDashboardData(siteId)
  const { notifications, reload: reloadNotifications } = useNotifications(siteId)
  const { nextReplanIn, refreshRollingEta } = useRollingReplanMinutes()

  const { fullStatus } = useFullStatus(siteId)
  const [alertsOpen, setAlertsOpen] = useState(false)
  const [inverterDiagOpen, setInverterDiagOpen] = useState(true)
  const [hiddenSeries, setHiddenSeries] = useState<Set<string>>(() => new Set())

  useEffect(() => {
    console.log('siteId:', siteId)
    console.log('inverterDiagOpen:', inverterDiagOpen)
  }, [siteId, inverterDiagOpen])
  const [chartArea, setChartArea] = useState<ChartArea | null>(null)

  const toggleSeries = useCallback((key: string) => {
    setHiddenSeries((prev) => {
      const n = new Set(prev)
      if (n.has(key)) n.delete(key)
      else n.add(key)
      return n
    })
  }, [])

  const onChartArea = useCallback((area: ChartArea) => {
    setChartArea(area)
  }, [])

  const site = siteRow
  const fetchError = data.error ?? siteErr
  const metricsLoading = !data.ready || !siteReady
  const monitoringAlerts = fullStatus?.alerts ?? []
  const hasMonitoringAlerts = monitoringAlerts.length > 0
  const monitoringHasError = monitoringAlerts.some((a) => a.level === 'error')
  const hbOnline = site?.ems_heartbeat_status === 'ok'

  /** Horní karty (FVE, spotřeba, síť, SoC, ceny): liveMetrics + buyNow/sellNow z useDashboardData (15s poll / WS). */
  const lm = data.liveMetrics

  const modeName = site?.active_mode ?? fullStatus?.operating_mode.mode_code ?? 'AUTO'
  const modeActivatedAt = site?.activated_at ?? fullStatus?.operating_mode.activated_at ?? null

  const handleReplan = useCallback(() => {
    if (siteId == null) return
    void postRunPlan(siteId, 'rolling')
      .then(() => {
        void data.reload()
        void refreshRollingEta()
        void reloadNotifications()
      })
      .catch(() => {
        /* ignore */
      })
  }, [siteId, data, refreshRollingEta, reloadNotifications])

  const handleImportPrices = useCallback(() => {
    if (siteId == null) return
    void postImportSitePrices(siteId)
      .then(() => {
        void data.reload()
        void reloadNotifications()
      })
      .catch(() => {
        /* ignore */
      })
  }, [siteId, data, reloadNotifications])

  const handleSwitchAuto = useCallback(() => {
    if (siteId == null) return
    void postSiteMode(siteId, {
      mode: 'AUTO',
      notes: 'Přepnuto z notifikace',
      valid_until: null,
    })
      .then(() => {
        void data.reload()
        void reloadNotifications()
      })
      .catch(() => {
        /* ignore */
      })
  }, [siteId, data, reloadNotifications])

  return (
    <div className="min-h-screen bg-gray-950 p-4 text-slate-100 md:p-8">
      <div className="mx-auto max-w-7xl space-y-6">
        {fetchError ? (
          <div
            className="flex flex-col gap-3 rounded-xl border border-red-500/40 bg-red-950/40 px-4 py-3 sm:flex-row sm:items-center sm:justify-between"
            role="alert"
          >
            <p className="text-sm font-medium text-red-200">{fetchError}</p>
            <button
              type="button"
              onClick={() => void data.reload()}
              className="rounded-lg bg-red-600 px-4 py-2 text-sm font-semibold text-white hover:bg-red-500"
            >
              Zkusit znovu
            </button>
          </div>
        ) : null}

        <header className="border-b border-slate-800/80 pb-5">
          <h1 className="text-2xl font-bold tracking-tight text-white">EMS Platform</h1>
          <p className="mt-1 text-sm text-slate-400">Přehled výkonů, režimů a cen</p>
        </header>

        {siteId != null ? (
          <ModeBar
            modeName={modeName}
            activatedAt={modeActivatedAt}
            nextReplanIn={nextReplanIn}
            onReplan={handleReplan}
            onModeChange={() => navigate('/settings')}
          />
        ) : null}

        {notifications.length > 0 ? (
          <NotificationBar
            notifications={notifications}
            onReplan={handleReplan}
            onImportPrices={handleImportPrices}
            onSwitchAuto={handleSwitchAuto}
          />
        ) : null}

        <section>
          <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-6">
            {metricsLoading ? (
              <>
                <MetricSkeleton />
                <MetricSkeleton />
                <MetricSkeleton />
                <MetricSkeleton />
                <MetricSkeleton />
                <MetricSkeleton />
              </>
            ) : site == null ? (
              <p className="col-span-full text-sm text-slate-500">Žádná aktivní lokalita ve vw_site_status.</p>
            ) : (
              <>
                <div className="rounded-xl border border-slate-800 border-l-4 border-l-amber-500/80 bg-slate-900/70 p-4 pl-3">
                  <p className="text-[10px] font-semibold uppercase tracking-wide text-slate-500">FVE</p>
                  <p className="mt-1 text-xl font-semibold tabular-nums text-amber-300">{fmtKw2(lm?.pv_w)}</p>
                  <Sun className="mt-2 h-5 w-5 text-amber-500/80" aria-hidden />
                </div>
                <div className="rounded-xl border border-slate-800 border-l-4 border-l-blue-500/80 bg-slate-900/70 p-4 pl-3">
                  <p className="text-[10px] font-semibold uppercase tracking-wide text-slate-500">Spotřeba</p>
                  <p className="mt-1 text-xl font-semibold tabular-nums text-blue-300">{fmtKw2(lm?.load_w)}</p>
                  <Activity className="mt-2 h-5 w-5 text-blue-500/80" aria-hidden />
                </div>
                <div className="rounded-xl border border-slate-800 border-l-4 border-l-red-500/80 bg-slate-900/70 p-4 pl-3">
                  <p className="text-[10px] font-semibold uppercase tracking-wide text-slate-500">Síť</p>
                  <p className="mt-1 text-xl font-semibold tabular-nums text-slate-100">{fmtKw2(lm?.grid_w)}</p>
                  <p className="mt-0.5 text-[10px] text-slate-500">
                    {lm?.grid_w == null ? '' : lm.grid_w >= 0 ? 'import' : 'export'}
                  </p>
                  <Zap className="mt-1 h-5 w-5 text-red-400/80" aria-hidden />
                </div>
                <div className="rounded-xl border border-slate-800 border-l-4 border-l-emerald-500/80 bg-slate-900/70 p-4 pl-3">
                  <p className="text-[10px] font-semibold uppercase tracking-wide text-slate-500">SOC</p>
                  <p className="mt-1 text-xl font-semibold tabular-nums text-emerald-300">{fmtSoc(lm?.bat_soc)}</p>
                  <Battery className="mt-2 h-5 w-5 text-emerald-500/80" aria-hidden />
                </div>
                <div className="rounded-xl border border-slate-800 border-l-4 border-l-rose-500/80 bg-slate-900/70 p-4 pl-3">
                  <p className="text-[10px] font-semibold uppercase tracking-wide text-slate-500">Cena nákup</p>
                  <p className="mt-1 text-lg font-semibold tabular-nums text-rose-200">
                    {fmtMoney3(data.buyNow)}
                  </p>
                  <p className="mt-1 text-[10px] text-slate-500">Aktuální 15min slot</p>
                </div>
                <div className="rounded-xl border border-slate-800 border-l-4 border-l-teal-500/80 bg-slate-900/70 p-4 pl-3">
                  <p className="text-[10px] font-semibold uppercase tracking-wide text-slate-500">Cena prodej</p>
                  <p
                    className={`mt-1 text-lg font-semibold tabular-nums ${
                      data.sellNow != null && data.sellNow < 0 ? 'text-red-300' : 'text-teal-200'
                    }`}
                  >
                    {fmtMoney3(data.sellNow)}
                  </p>
                  <p className="mt-1 text-[10px] text-slate-500">Aktuální 15min slot</p>
                </div>
              </>
            )}
          </div>

          {!metricsLoading && site != null ? (
            <div className="mt-4 space-y-3 text-sm">
              <div className="flex flex-wrap items-center gap-3">
                <span className="text-slate-500">Režim:</span>
                <span className="rounded-md bg-slate-800 px-2 py-1 text-xs font-semibold uppercase text-slate-200">
                  {site.active_mode ?? '—'}
                  {site.mode_name ? ` · ${site.mode_name}` : ''}
                </span>
                <span className="flex items-center gap-2 text-slate-400">
                  <span
                    className={`inline-flex h-2.5 w-2.5 rounded-full ${hbOnline ? 'bg-emerald-500' : 'bg-red-500'}`}
                  />
                  EMS:{' '}
                  <span className={hbOnline ? 'text-emerald-400' : 'text-red-400'}>
                    {hbOnline ? 'online' : 'offline'}
                  </span>
                </span>
              </div>

              {hasMonitoringAlerts ? (
                <div className="max-w-2xl">
                  <button
                    type="button"
                    onClick={() => setAlertsOpen((o) => !o)}
                    className={`flex w-full items-center justify-between gap-3 rounded-lg border px-3 py-2 text-left text-sm font-medium transition hover:opacity-95 ${
                      monitoringHasError
                        ? 'border-red-500/45 bg-red-950/45 text-red-100'
                        : 'border-amber-500/40 bg-amber-950/35 text-amber-100'
                    }`}
                    aria-expanded={alertsOpen}
                  >
                    <span>
                      {monitoringAlerts.length}{' '}
                      {monitoringAlerts.length === 1 ? 'alert' : 'alertů'}
                    </span>
                    {alertsOpen ? (
                      <ChevronUp className="h-4 w-4 shrink-0 opacity-80" aria-hidden />
                    ) : (
                      <ChevronDown className="h-4 w-4 shrink-0 opacity-80" aria-hidden />
                    )}
                  </button>
                  {alertsOpen ? (
                    <ul
                      className={`mt-2 space-y-1.5 rounded-lg border px-3 py-2 text-sm ${
                        monitoringHasError
                          ? 'border-red-500/30 bg-red-950/25 text-red-100'
                          : 'border-amber-500/25 bg-amber-950/20 text-amber-50'
                      }`}
                    >
                      {monitoringAlerts.map((a, i) => (
                        <li key={`${a.level}-${i}`} className={a.level === 'error' ? 'text-red-200' : 'text-amber-200'}>
                          <span className="text-[10px] font-semibold uppercase opacity-80">
                            {a.level === 'error' ? 'Chyba' : 'Varování'}
                          </span>
                          <span className="ml-2">{a.message}</span>
                        </li>
                      ))}
                    </ul>
                  ) : null}
                </div>
              ) : null}
            </div>
          ) : null}
        </section>

        <section>
          {data.slots.length === 0 && data.slotsReady ? (
            <div className="rounded-xl border border-slate-800 bg-slate-900/40 px-4 py-8 text-center text-sm text-slate-500">
              Nedostatek dat pro graf (zkontrolujte plán a telemetrii).
            </div>
          ) : (
            <div className="overflow-hidden rounded-xl border border-slate-800 bg-slate-900/40">
              <div className="px-2 pb-1 pt-2">
                <MemoEnergyChart
                  slots={data.slots}
                  nowIndex={data.nowIndex}
                  hidden={hiddenSeries}
                  onToggle={toggleSeries}
                  onChartArea={onChartArea}
                />
              </div>
              <MemoRegimeBar
                slots={data.slots}
                nowIndex={data.nowIndex}
                chartPaddingLeft={CHART_LAYOUT_PADDING.left}
                chartPaddingRight={CHART_LAYOUT_PADDING.right}
                chartArea={chartArea}
              />
              <div className="border-t border-slate-800 px-2 py-2">
                <MemoSocTuvChart
                  slots={data.slots}
                  nowIndex={data.nowIndex}
                  liveBatSoc={data.liveMetrics?.bat_soc ?? null}
                />
              </div>
            </div>
          )}
        </section>

        {data.slots.length > 0 && data.slotsReady ? (
          <section>
            <StatePanel slots={data.slots} nowIndex={data.nowIndex} />
            {siteId != null && (
              <div className="mt-4">
                <PoolCard siteId={siteId} />
              </div>
            )}
          </section>
        ) : null}

        {siteId != null ? (
          <section className="rounded-xl border border-slate-800 bg-slate-900/40">
            <button
              type="button"
              onClick={() => setInverterDiagOpen((o) => !o)}
              className="flex w-full items-center justify-between gap-3 px-4 py-3 text-left text-sm font-medium text-slate-200 transition hover:bg-slate-800/30"
              aria-expanded={inverterDiagOpen}
            >
              <span>Diagnostika střídače (Deye · Modbus)</span>
              {inverterDiagOpen ? (
                <ChevronUp className="h-4 w-4 shrink-0 text-slate-400" aria-hidden />
              ) : (
                <ChevronDown className="h-4 w-4 shrink-0 text-slate-400" aria-hidden />
              )}
            </button>
            {inverterDiagOpen ? (
              <div className="border-t border-slate-800 p-4">
                <ControlPanel siteId={siteId} />
              </div>
            ) : null}
          </section>
        ) : null}

        <section className="grid grid-cols-1 gap-4 lg:grid-cols-2 lg:gap-6">
          <ForecastPanel days={data.forecastWeek} />
          <NegPricePanel items={data.negPrices} />
        </section>
      </div>
    </div>
  )
}
