"use client";

import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import { Line, Chart } from 'react-chartjs-2';
import {
  Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement,
  BarElement, Tooltip, Legend, Filler,
} from 'chart.js';
import { SankeyController, Flow } from 'chartjs-chart-sankey';
import { ADMIN_REFRESH_EVENT } from '@/components/admin-nav';
import { formatLabelInTz, REPORTING_TZ } from '@/lib/timezone';

ChartJS.register(
  CategoryScale, LinearScale, PointElement, LineElement, BarElement, Tooltip, Legend, Filler,
  SankeyController, Flow,
);

interface StatsPayload {
  lifetime: {
    sessions: number;
    matches: number;
    swipes: number;
    swipesYes: number;
    participants: number;
    jokerDraws: number;
    matchesPerSession: number;
    sessionsWithMatch: number;
  };
  live: {
    sessions: number;
    sessionsActive: number;
    sessionsLive: number;
    usersLive: number;
    sessionsToday: number;
    sessions7d: number;
    matches: number;
    matchesToday: number;
    matches7d: number;
    sessionsWithMatch: number;
    participants: number;
    swipes: number;
    swipesYes: number;
    jokerDraws: number;
    restaurantsCached: number;
    sponsorsActive: number;
    matchSessionRatePct: number;
  };
  topCities: { city: string; cnt: number }[];
  topCitiesToday: { city: string; cnt: number }[];
  topCities7d: { city: string; cnt: number }[];
  topCities30d: { city: string; cnt: number }[];
  topCities365d: { city: string; cnt: number }[];
  trendToday: { labels: string[]; sessions: number[]; matches: number[] };
  trend7d: { labels: string[]; sessions: number[]; matches: number[] };
  trend30d: { labels: string[]; sessions: number[]; matches: number[] };
  trend365d: { labels: string[]; sessions: number[]; matches: number[] };
  funnel: { started: number; withMatch: number; forwards: number; withMatchPct: number; forwardsPct: number };
  funnelToday: { started: number; withMatch: number; forwards: number; withMatchPct: number; forwardsPct: number };
  funnel7d: { started: number; withMatch: number; forwards: number; withMatchPct: number; forwardsPct: number };
  funnel30d: { started: number; withMatch: number; forwards: number; withMatchPct: number; forwardsPct: number };
  funnel365d: { started: number; withMatch: number; forwards: number; withMatchPct: number; forwardsPct: number };
  outboundClicks: { total: number; byType: { type: string; label: string; cnt: number }[] };
  outboundClicksToday: { total: number; byType: { type: string; label: string; cnt: number }[] };
  outboundClicks7d: { total: number; byType: { type: string; label: string; cnt: number }[] };
  outboundClicks30d: { total: number; byType: { type: string; label: string; cnt: number }[] };
  outboundClicks365d: { total: number; byType: { type: string; label: string; cnt: number }[] };
  retention: { totalVisitors: number; returningVisitors: number; returningPct: number };
  liveSessions: {
    id: number;
    code: string;
    city: string;
    expires_at: string;
    last_activity_at: string;
    participant_count: number;
    has_match: number;
  }[];
}

const ACCENT = {
  pink: '#FE3C72',
  teal: '#00C2A8',
  blue: '#3b82f6',
  indigo: '#6366f1',
  amber: '#f59f00',
};

function StatCard({
  label, value, sub, accent = 'pink',
}: {
  label: string;
  value: string | number;
  sub?: string;
  accent?: 'pink' | 'teal' | 'blue' | 'indigo' | 'amber';
}) {
  const valueClsMap: Record<string, string> = {
    pink: 'text-yumder-pink',
    teal: 'text-yumder-teal',
    blue: 'text-blue-600',
    indigo: 'text-indigo-600',
    amber: 'text-amber-600',
  };
  const accentMap: Record<string, string> = {
    pink: 'bg-pink-50 text-yumder-pink',
    teal: 'bg-teal-50 text-yumder-teal',
    blue: 'bg-blue-50 text-blue-600',
    indigo: 'bg-indigo-50 text-indigo-600',
    amber: 'bg-amber-50 text-amber-600',
  };
  const valueCls = valueClsMap[accent] ?? 'text-yumder-pink';
  const accentCls = accentMap[accent] ?? 'bg-pink-50 text-yumder-pink';

  return (
    <div className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm transition-colors duration-200 hover:border-slate-300 hover:shadow-md">
      <div>
        <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">{label}</p>
        <p className={`mt-3 text-3xl font-bold tabular-nums leading-none ${valueCls}`}>{value}</p>
      </div>
      {sub && <p className="mt-3 text-xs text-slate-500">{sub}</p>}
    </div>
  );
}

function HeroCard({ value, sub }: { value: string; sub: string }) {
  return (
    <div className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm">
      <div className="flex items-center gap-3">
        <span className="inline-block h-2.5 w-2.5 rounded-full bg-yumder-pink" />
        <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Match-Quote (Gesamt)</p>
      </div>
      <p className="mt-4 text-4xl font-extrabold tracking-tight tabular-nums leading-none text-slate-900">
        {value}
      </p>
      <p className="mt-2 text-xs text-slate-500">{sub}</p>
    </div>
  );
}

function formatDayLabel(iso: string): string {
  return formatLabelInTz(iso, REPORTING_TZ, { weekday: 'short' });
}

function formatMonthLabel(iso: string): string {
  return formatLabelInTz(iso, REPORTING_TZ, { month: 'short' });
}

function minutesSince(sqliteUtc: string): number {
  const t = new Date(sqliteUtc.replace(' ', 'T') + 'Z').getTime();
  return Math.max(0, Math.round((Date.now() - t) / 60000));
}

function getPeakLabel(labels: string[], values: number[]) {
  if (!labels.length || !values.length) return '—';
  const idx = values.reduce((best, value, i, arr) => (value > arr[best] ? i : best), 0);
  return labels[idx];
}

function getTrendDelta(values: number[]) {
  if (values.length < 2) return 'Trend stabil';
  const first = values[0] ?? 0;
  const last = values[values.length - 1] ?? 0;
  const delta = first === 0 ? (last > 0 ? 100 : 0) : Math.round(((last - first) / first) * 100);
  return `${delta >= 0 ? '↑' : '↓'} ${Math.abs(delta)}%`;
}

const SANKEY_COLORS: Record<string, string> = {
  'Gestartete Sessions': ACCENT.blue,
  'Sessions mit Match': ACCENT.pink,
  'Sessions ohne Match': '#adb5bd',
  'Klicks gesamt': ACCENT.indigo,
  'Route/Maps': '#4dabf7',
  'Anrufen': ACCENT.teal,
  'Webseite': ACCENT.pink,
  'Reservieren': ACCENT.amber,
  'Bestellen': '#748ffc',
};

function sankeyColor(label: string): string {
  return SANKEY_COLORS[label] ?? '#adb5bd';
}

export default function AdminOverviewPage() {
  const router = useRouter();
  const [stats, setStats] = useState<StatsPayload | null>(null);
  const [loading, setLoading] = useState(true);
  const [range, setRange] = useState<'today' | '7d' | '30d' | '365d'>('7d');

  async function loadStats(silent = false, force = false) {
    if (!silent) setLoading(true);
    try {
      const res = await fetch(force ? '/api/admin/stats?refresh=1' : '/api/admin/stats');
      if (res.status === 401) {
        router.push('/admin');
        return;
      }
      if (!res.ok) return;
      setStats(await res.json());
    } finally {
      if (!silent) setLoading(false);
    }
  }

  useEffect(() => { loadStats(); }, []);

  useEffect(() => {
    const handleRefresh = () => loadStats(true, true);
    window.addEventListener(ADMIN_REFRESH_EVENT, handleRefresh);
    return () => window.removeEventListener(ADMIN_REFRESH_EVENT, handleRefresh);
  }, []);

  useEffect(() => {
    const id = setInterval(() => loadStats(true), 60000);
    return () => clearInterval(id);
  }, []);

  const L = stats?.lifetime;
  const V = stats?.live;
  const funnelByRange = {
    today: stats?.funnelToday,
    '7d': stats?.funnel7d,
    '30d': stats?.funnel30d,
    '365d': stats?.funnel365d,
  };
  const F = funnelByRange[range] ?? stats?.funnel;
  const trendByRange = {
    today: stats?.trendToday,
    '7d': stats?.trend7d,
    '30d': stats?.trend30d,
    '365d': stats?.trend365d,
  };
  const T = trendByRange[range] ?? stats?.trend7d;
  const clickByRange = {
    today: stats?.outboundClicksToday,
    '7d': stats?.outboundClicks7d,
    '30d': stats?.outboundClicks30d,
    '365d': stats?.outboundClicks365d,
  };
  const OC = clickByRange[range] ?? stats?.outboundClicks;
  const R = stats?.retention;
  const topCitiesByRange = {
    today: stats?.topCitiesToday,
    '7d': stats?.topCities7d,
    '30d': stats?.topCities30d,
    '365d': stats?.topCities365d,
  };
  const topCities = topCitiesByRange[range] ?? stats?.topCities ?? [];

  const sessionSankeyData = F
    ? [
        { from: 'Gestartete Sessions', to: 'Sessions mit Match', flow: F.withMatch },
        { from: 'Gestartete Sessions', to: 'Sessions ohne Match', flow: Math.max(F.started - F.withMatch, 0) },
      ]
    : [];

  const clickSankeyData = OC
    ? OC.byType.map((t) => ({ from: 'Klicks gesamt', to: t.label, flow: t.cnt }))
    : [];

  const peakLabel = T ? getPeakLabel(T.labels, T.sessions) : '—';
  const strongestDayLabel = T ? getPeakLabel(T.labels, T.sessions) : '—';
  const peakMetricLabel = range === 'today' ? 'Spitzenstunde' : 'Stärkster Tag';

  return (
    <div className="p-6 lg:p-8 pb-24">
      <div className="max-w-6xl mx-auto">
        <div className="mb-4 flex items-center justify-between gap-3">
          <div>
            <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Übersicht</p>
          </div>
          <div className="flex items-center gap-2 rounded-full border border-slate-200 bg-white p-1 shadow-sm">
            {(['today', '7d', '30d', '365d'] as const).map((option) => (
              <button
                key={option}
                type="button"
                onClick={() => setRange(option)}
                className={`rounded-full px-3 py-1.5 text-xs font-semibold transition-colors ${
                  range === option ? 'bg-slate-900 text-white' : 'text-slate-600 hover:text-slate-900'
                }`}
              >
                {option === 'today' ? 'Heute' : option === '7d' ? '7 Tage' : option === '30d' ? '30 Tage' : '365 Tage'}
              </button>
            ))}
          </div>
        </div>

        {loading && !stats ? (
          <p className="text-sm text-slate-500">Lade Statistiken...</p>
        ) : stats && L && V && F && T && OC && R ? (
          <div className="flex flex-col gap-5">
            <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
              <StatCard label="Live-Sessions" value={V.sessionsLive} sub={`${V.sessionsActive} aktive Sessions`} accent="teal" />
              <StatCard label="Aktive Nutzer" value={V.usersLive} sub="in den letzten 5 Minuten" accent="indigo" />
              <HeroCard
                value={`${L.matchesPerSession}%`}
                sub={`${L.sessionsWithMatch} Sessions mit Match`}
              />
              <StatCard label="Matches gesamt" value={L.matches} sub={`${V.matchesToday} heute`} accent="indigo" />
              <StatCard
                label="Swipes gesamt"
                value={L.swipes.toLocaleString('de-DE')}
                sub={`${L.swipesYes.toLocaleString('de-DE')} mit Ja`}
                accent="blue"
              />
              <StatCard
                label="Sponsoren aktiv"
                value={V.sponsorsActive}
                sub={`${V.restaurantsCached.toLocaleString('de-DE')} Restaurants`}
                accent="amber"
              />
            </div>

            <div className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm">
              <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500 mb-4">
                Live-Sessions (letzte 5 Minuten)
              </p>
              {stats.liveSessions.length === 0 ? (
                <p className="text-sm text-slate-500">Derzeit keine aktiven Sessions.</p>
              ) : (
                <ul className="divide-y divide-slate-100">
                  {stats.liveSessions.map((s) => (
                    <li key={s.id} className="flex items-center justify-between gap-3 py-2.5 text-sm">
                      <div className="flex items-center gap-3 min-w-0">
                        <span className="font-mono font-semibold text-slate-900">{s.code}</span>
                        <span className="text-slate-500 truncate">{s.city}</span>
                        {s.has_match === 1 && (
                          <span className="shrink-0 text-[10px] font-bold uppercase px-2 py-0.5 rounded-full bg-yumder-pink/10 text-yumder-pink">
                            Match
                          </span>
                        )}
                      </div>
                      <div className="flex items-center gap-3 shrink-0">
                        <span className="text-slate-500">{s.participant_count} Teiln.</span>
                        <span className="text-slate-400 text-xs">vor {minutesSince(s.last_activity_at)} Min.</span>
                      </div>
                    </li>
                  ))}
                </ul>
              )}
            </div>

            <div className="space-y-2">
              <p className="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">Trends</p>
              <div className="grid gap-3 md:grid-cols-3">
                <div className="rounded-2xl border border-slate-900 bg-slate-900 px-4 py-3 text-white shadow-sm">
                  <p className="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-300">{peakMetricLabel}</p>
                  <p className="mt-2 text-lg font-bold text-white">{peakLabel}</p>
                  <p className="mt-1 text-[11px] font-medium text-slate-200">{getTrendDelta(T.sessions)}</p>
                </div>
                <div className="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3">
                  <p className="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">Aktivster Zeitraum</p>
                  <p className="mt-2 text-lg font-bold text-slate-900">{strongestDayLabel}</p>
                  <p className="mt-1 text-[11px] font-medium text-emerald-600">{getTrendDelta(T.matches)}</p>
                </div>
                <div className="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3">
                  <p className="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">Sessions/Match</p>
                  <p className="mt-2 text-lg font-bold text-slate-900">{F.withMatchPct}%</p>
                  <p className="mt-1 text-[11px] font-medium text-sky-600">{F.withMatchPct >= 50 ? 'Stark' : 'Wachstum'}</p>
                </div>
              </div>
            </div>

            <div className="grid gap-4 xl:grid-cols-[1.2fr_1.8fr]">
              <div className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm">
                <div className="flex items-center justify-between gap-3">
                  <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Wiederkehrer-Rate</p>
                  <span className="rounded-full bg-emerald-50 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-emerald-700">
                    LTV Signal
                  </span>
                </div>
                <p className="mt-4 text-4xl font-extrabold tracking-tight tabular-nums leading-none text-slate-900">
                  {R.returningPct}%
                </p>
                <p className="mt-2 text-sm text-slate-500">
                  {R.returningVisitors} von {R.totalVisitors} Nutzern kamen wieder
                </p>
              </div>

              <div className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm">
                <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Was bedeutet das?</p>
                <p className="mt-3 text-sm leading-6 text-slate-600">
                  Erfasst, wie viele eindeutige Geräte an mehr als einer Yumder-Session teilgenommen haben.
                  Da der Service ohne Accounts läuft, basiert die Erkennung auf einer gerätegebundenen ID.
                  Browser-Cache oder Privat-Modus können die Zahl leicht unterschätzen; der echte Wert liegt
                  mindestens bei diesem Niveau und ist damit ein starkes Argument für Sponsoring-Anfragen.
                </p>
              </div>
            </div>

            <div className="grid gap-4 lg:grid-cols-2">
              <div className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
                <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500 mb-5">
                  Session-Ausgang · {range === 'today' ? 'Heute' : range === '7d' ? '7 Tage' : range === '30d' ? '30 Tage' : '365 Tage'}
                </p>
                <div className="h-64">
                  <Chart
                    type={'sankey' as any}
                    data={{
                      datasets: [{
                        label: 'Sessions',
                        data: sessionSankeyData,
                        colorFrom: (c: any) => sankeyColor(c.dataset.data[c.dataIndex].from),
                        colorTo: (c: any) => sankeyColor(c.dataset.data[c.dataIndex].to),
                        colorMode: 'gradient',
                      } as any],
                    }}
                    options={{
                      responsive: true,
                      maintainAspectRatio: false,
                      plugins: { legend: { display: false } },
                    } as any}
                  />
                </div>
                <p className="mt-4 text-xs text-slate-500">
                  {F.started} gestartete Sessions gesamt · {F.withMatchPct}% davon mit Match.
                </p>
              </div>

              <div className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
                <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500 mb-5">
                  Klick-Verteilung · {range === 'today' ? 'Heute' : range === '7d' ? '7 Tage' : range === '30d' ? '30 Tage' : '365 Tage'}
                </p>
                <div className="h-64">
                  {clickSankeyData.length > 0 ? (
                    <Chart
                      type={'sankey' as any}
                      data={{
                        datasets: [{
                          label: 'Klicks',
                          data: clickSankeyData,
                          colorFrom: (c: any) => sankeyColor(c.dataset.data[c.dataIndex].from),
                          colorTo: (c: any) => sankeyColor(c.dataset.data[c.dataIndex].to),
                          colorMode: 'gradient',
                        } as any],
                      }}
                      options={{
                        responsive: true,
                        maintainAspectRatio: false,
                        plugins: { legend: { display: false } },
                      } as any}
                    />
                  ) : (
                    <p className="text-sm text-slate-500">Noch keine Klicks erfasst.</p>
                  )}
                </div>
                <p className="mt-4 text-xs text-slate-500">
                  {OC.total} {OC.total === 1 ? 'Klick' : 'Klicks'} gesamt, aufgeteilt nach Aktionstyp.
                </p>
              </div>
            </div>

            <div className="grid gap-4 xl:grid-cols-[1.8fr_1fr]">
              <div className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
                <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500 mb-4">
                  Sessions & Matches ({range === 'today' ? 'Heute' : range === '7d' ? 'Letzte 7 Tage' : range === '30d' ? 'Letzte 30 Tage' : 'Letzte 365 Tage'})
                </p>
                <div className="h-64">
                  <Line
                    data={{
                      labels: T.labels.map((label) => {
                        if (range === 'today') return label;
                        if (range === '365d') return formatMonthLabel(label);
                        return formatLabelInTz(label, REPORTING_TZ, { day: '2-digit', month: '2-digit' });
                      }),
                      datasets: [
                        {
                          label: 'Sessions',
                          data: T.sessions,
                          borderColor: ACCENT.blue,
                          backgroundColor: 'rgba(59, 130, 246, 0.1)',
                          borderWidth: 3,
                          fill: true,
                          tension: 0.3,
                        },
                        {
                          label: 'Matches',
                          data: T.matches,
                          borderColor: ACCENT.pink,
                          backgroundColor: 'rgba(254, 60, 114, 0.1)',
                          borderWidth: 3,
                          fill: true,
                          tension: 0.3,
                        },
                      ],
                    }}
                    options={{
                      responsive: true,
                      maintainAspectRatio: false,
                      plugins: {
                        legend: { position: 'top', labels: { usePointStyle: true, boxWidth: 8 } },
                      },
                      scales: {
                        y: { beginAtZero: true, grid: { color: '#e9ecef' } },
                        x: { grid: { display: false } },
                      },
                    }}
                  />
                </div>
              </div>

              <div className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
                <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500 mb-4">
                  Top-Städte
                </p>

                {topCities.length > 0 ? (
                  <div className="flex flex-col">
                    {topCities.slice(0, 3).map((c, i) => (
                      <div
                        key={c.city}
                        className={`flex justify-between py-3 text-sm ${i < 2 ? 'border-b border-slate-200' : ''}`}
                      >
                        <span className="text-slate-500">{c.city}</span>
                        <strong className="text-slate-900">{c.cnt}</strong>
                      </div>
                    ))}
                  </div>
                ) : (
                  <p className="text-sm text-slate-500">Noch keine Städte erfasst.</p>
                )}
              </div>
            </div>
          </div>
        ) : (
          <p className="text-sm text-slate-500">Statistiken nicht verfügbar.</p>
        )}
      </div>
    </div>
  );
}
