"use client";

import * as React from "react";
import Link from "next/link";
import { LayoutGroup, motion } from "motion/react";
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Line, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, ComposedChart } from "recharts";
import { ArrowDownRight, ArrowUpRight, LogIn, LogOut, Users } from "lucide-react";
import { cn } from "@/lib/utils";
import type { CommandCenterData } from "@/lib/queries/command-center";
import { Card, CardHeader, CardContent } from "@/components/ui/card";
import { Switch, Tooltip as Tip } from "@/components/ui/primitives";
import { fmtMoney, fmtNumber, fmtPercent } from "@/lib/format";
import { CountUp } from "./count-up";
import { TiltCard } from "@/components/motion/tilt-card";

type Metric = "revenue" | "profit" | "expenses" | "reservations" | "occupancy";
const METRICS: { key: Metric; label: string; money: boolean; color: string }[] = [
  { key: "revenue", label: "Revenue", money: true, color: "var(--color-primary)" },
  { key: "profit", label: "Profit", money: true, color: "var(--color-positive-500)" },
  { key: "expenses", label: "Expenses", money: true, color: "var(--color-gold-500)" },
  { key: "reservations", label: "Reservations", money: false, color: "var(--color-info-500)" },
  { key: "occupancy", label: "Occupancy", money: false, color: "var(--color-accent-500)" },
];

function RichTooltip({ active, payload, currency }: { active?: boolean; payload?: { payload: CommandCenterData["trend"][number] }[]; currency: string }) {
  if (!active || !payload?.length) return null;
  const p = payload[0].payload;
  const rows: [string, string, string?][] = [
    ["Revenue", fmtMoney(p.revenue, currency), "text-fg"],
    ["Previous period", fmtMoney(p.previous, currency), "text-fg-muted"],
    ["Expenses", fmtMoney(p.expenses, currency), "text-warning-600"],
    ["Profit", fmtMoney(p.profit, currency), p.profit >= 0 ? "text-positive-600" : "text-negative-600"],
    ["Reservations", fmtNumber(p.reservations)],
    ["Occupancy", fmtPercent(p.occupancy, 0)],
    ["Check-ins · outs", `${p.checkIns} · ${p.checkOuts}`],
  ];
  return (
    <div className="min-w-[200px] rounded-xl border border-border bg-surface/95 p-3 text-xs shadow-xl backdrop-blur animate-scale-in">
      <p className="mb-2 font-semibold text-fg">{p.label}</p>
      {rows.map(([k, v, cls]) => (
        <div key={k} className="flex items-center justify-between gap-4 py-0.5">
          <span className="text-fg-muted">{k}</span>
          <span className={cn("font-medium tabular", cls)}>{v}</span>
        </div>
      ))}
    </div>
  );
}

function MiniRing({ value, size = 56, color = "var(--color-primary)", children }: { value: number; size?: number; color?: string; children?: React.ReactNode }) {
  const stroke = 5;
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const v = Math.max(0, Math.min(100, value));
  return (
    <span className="relative inline-flex shrink-0 items-center justify-center" style={{ width: size, height: size }}>
      <svg width={size} height={size} className="-rotate-90">
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--color-surface-3)" strokeWidth={stroke} />
        <motion.circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeDasharray={c} initial={{ strokeDashoffset: c }} animate={{ strokeDashoffset: c - (c * v) / 100 }} transition={{ duration: 1.1, ease: [0.16, 1, 0.3, 1] }} />
      </svg>
      <span className="absolute inset-0 flex items-center justify-center text-xs font-semibold tabular">{children}</span>
    </span>
  );
}

function Segmented({ parts, total }: { parts: { key: string; value: number; color: string; label: string }[]; total: number }) {
  return (
    <div className="flex h-2.5 w-full overflow-hidden rounded-full bg-surface-3">
      {parts.map((p) => (
        <Tip key={p.key} content={`${p.label} · ${Math.round((p.value / Math.max(1, total)) * 100)}%`}>
          <motion.span className="h-full" style={{ background: p.color }} initial={{ width: 0 }} animate={{ width: `${(p.value / Math.max(1, total)) * 100}%` }} transition={{ duration: 0.9, ease: [0.16, 1, 0.3, 1] }} />
        </Tip>
      ))}
    </div>
  );
}

/**
 * Flagship analytics card. The chart grows to fill the row, and the band
 * below it turns the same live payload into four operational pulses: tonight,
 * money flow, channel mix and the best/weakest days of the period.
 */
export function FlagshipChart({ trend, period, hero, ops, forecast, bySource, currency, showProfit, className, loading }: { trend: CommandCenterData["trend"]; period: CommandCenterData["period"]; hero: CommandCenterData["hero"]; ops: CommandCenterData["ops"]; forecast: CommandCenterData["forecast"]; bySource: CommandCenterData["bySource"]; currency: string; showProfit: boolean; className?: string; loading: boolean }) {
  const [metric, setMetric] = React.useState<Metric>("revenue");
  const [compare, setCompare] = React.useState(true);
  const m = METRICS.find((x) => x.key === metric)!;
  const id = React.useId();
  const fmt = (v: number) => (m.money ? (Math.abs(v) >= 1000 ? `${(v / 1000).toFixed(v % 1000 === 0 ? 0 : 1)}k` : String(v)) : metric === "occupancy" ? `${v}%` : String(v));
  const bars = trend.length <= 14;
  const money = (v: number) => fmtMoney(v, currency, { compact: true, whole: true });

  const values = trend.map((t) => t[metric]);
  const avg = values.length ? values.reduce((s, v) => s + v, 0) / values.length : 0;
  const best = trend.reduce<CommandCenterData["trend"][number] | null>((b, t) => (!b || t.revenue > b.revenue ? t : b), null);
  const weakest = trend.reduce<CommandCenterData["trend"][number] | null>((b, t) => (!b || t.revenue < b.revenue ? t : b), null);
  const maxRev = Math.max(1, ...trend.map((t) => t.revenue));
  const thisTotal = values.reduce((s, v) => s + v, 0);
  const prevTotal = trend.reduce((s, t) => s + t.previous, 0);
  const delta = metric === "revenue" && prevTotal > 0 ? ((thisTotal - prevTotal) / prevTotal) * 100 : null;
  const sources = [...bySource].sort((a, b) => b.revenue - a.revenue);
  const sourceTotal = sources.reduce((s, x) => s + x.revenue, 0);
  const tonight = forecast.today;

  return (
    <Card className={cn("flex flex-col overflow-hidden", className)}>
      <CardHeader
        title={
          <span className="flex items-center gap-2">
            Revenue analytics <span className="live-dot" aria-label="Live" />
          </span>
        }
        description={`${period.label} · ${trend.length} ${trend.length === period.days ? "days" : "periods"}${delta != null ? ` · ${delta >= 0 ? "+" : ""}${delta.toFixed(1)}% vs previous` : ""}`}
        action={
          <div className="flex flex-wrap items-center gap-2">
            <LayoutGroup id="flagship-metric">
              <div className="flex shrink-0 gap-0.5 rounded-lg bg-surface-2 p-0.5">
                {METRICS.filter((x) => showProfit || x.key !== "profit").map((x) => (
                  <button key={x.key} type="button" onClick={() => setMetric(x.key)} className={cn("relative rounded-md px-2 py-1 text-xs font-medium transition-colors", metric === x.key ? "text-fg" : "text-fg-muted hover:text-fg")}>
                    {metric === x.key ? <motion.span layoutId="metric-pill" transition={{ type: "spring", stiffness: 520, damping: 40 }} className="absolute inset-0 rounded-md bg-surface shadow-xs" aria-hidden /> : null}
                    <span className="relative flex items-center gap-1.5">
                      <span className="size-1.5 rounded-full" style={{ background: x.color }} />
                      {x.label}
                    </span>
                  </button>
                ))}
              </div>
            </LayoutGroup>
            {metric === "revenue" ? (
              <label className="flex items-center gap-1.5 text-xs text-fg-muted">
                <Switch size="sm" checked={compare} onCheckedChange={setCompare} /> Compare
              </label>
            ) : null}
          </div>
        }
      />
      <CardContent className={cn("flex flex-1 flex-col transition-opacity duration-300", loading && "opacity-60")}>
        <div className="flex items-baseline gap-3 pb-2">
          <p className="font-display text-2xl font-medium tracking-tight tabular">
            <CountUp value={metric === "occupancy" ? avg : thisTotal} format={(v) => (m.money ? money(v) : metric === "occupancy" ? fmtPercent(v, 0) : fmtNumber(Math.round(v)))} />
          </p>
          <p className="text-xs text-fg-muted">
            {metric === "occupancy" ? "average" : "total"} · avg {m.money ? money(avg) : metric === "occupancy" ? fmtPercent(avg, 0) : fmtNumber(Math.round(avg))} per {trend.length === period.days ? "day" : "period"}
          </p>
          {delta != null ? (
            <span className={cn("inline-flex items-center gap-0.5 rounded-full px-2 py-0.5 text-2xs font-semibold tabular", delta >= 0 ? "bg-positive-500/10 text-positive-600" : "bg-negative-500/10 text-negative-600")}>
              {delta >= 0 ? <ArrowUpRight className="size-3" /> : <ArrowDownRight className="size-3" />}
              {Math.abs(delta).toFixed(1)}%
            </span>
          ) : null}
        </div>
        <div className="min-h-[260px] w-full flex-1">
          <ResponsiveContainer width="100%" height="100%">
            {bars ? (
              <ComposedChart data={trend} margin={{ top: 8, right: 8, left: -8, bottom: 0 }}>
                <defs>
                  <linearGradient id={`${id}-bar`} x1="0" x2="0" y1="0" y2="1">
                    <stop offset="0%" stopColor={m.color} stopOpacity={1} />
                    <stop offset="100%" stopColor={m.color} stopOpacity={0.55} />
                  </linearGradient>
                </defs>
                <CartesianGrid vertical={false} strokeDasharray="3 3" />
                <XAxis dataKey="label" tickLine={false} axisLine={false} fontSize={11} tick={{ fill: "var(--color-fg-muted)" }} interval="preserveStartEnd" minTickGap={18} />
                <YAxis tickLine={false} axisLine={false} fontSize={11} tick={{ fill: "var(--color-fg-muted)" }} tickFormatter={fmt} width={44} />
                <Tooltip content={<RichTooltip currency={currency} />} cursor={{ fill: "color-mix(in oklab, var(--color-primary) 6%, transparent)" }} />
                <ReferenceLine y={avg} stroke={m.color} strokeOpacity={0.35} strokeDasharray="2 4" />
                <Bar dataKey={metric} fill={`url(#${id}-bar)`} radius={[6, 6, 0, 0]} maxBarSize={38} isAnimationActive animationDuration={650} animationEasing="ease-out" />
                {metric === "revenue" && compare ? <Line type="monotone" dataKey="previous" stroke="var(--color-stone-400)" strokeDasharray="4 4" strokeWidth={1.5} dot={false} isAnimationActive animationDuration={650} /> : null}
              </ComposedChart>
            ) : (
              <AreaChart data={trend} margin={{ top: 8, right: 8, left: -8, bottom: 0 }}>
                <defs>
                  <linearGradient id={id} x1="0" x2="0" y1="0" y2="1">
                    <stop offset="0%" stopColor={m.color} stopOpacity={0.35} />
                    <stop offset="100%" stopColor={m.color} stopOpacity={0} />
                  </linearGradient>
                </defs>
                <CartesianGrid vertical={false} strokeDasharray="3 3" />
                <XAxis dataKey="label" tickLine={false} axisLine={false} fontSize={11} tick={{ fill: "var(--color-fg-muted)" }} interval="preserveStartEnd" minTickGap={24} />
                <YAxis tickLine={false} axisLine={false} fontSize={11} tick={{ fill: "var(--color-fg-muted)" }} tickFormatter={fmt} width={44} />
                <Tooltip content={<RichTooltip currency={currency} />} cursor={{ stroke: "var(--color-border-strong)", strokeDasharray: "3 3" }} />
                <ReferenceLine y={avg} stroke={m.color} strokeOpacity={0.35} strokeDasharray="2 4" />
                {metric === "revenue" && compare ? <Area type="monotone" dataKey="previous" stroke="var(--color-stone-400)" strokeDasharray="4 4" strokeWidth={1.5} fill="none" dot={false} isAnimationActive animationDuration={650} /> : null}
                <Area type="monotone" dataKey={metric} stroke={m.color} strokeWidth={2.4} fill={`url(#${id})`} activeDot={{ r: 5, strokeWidth: 0 }} isAnimationActive animationDuration={800} animationEasing="ease-out" />
              </AreaChart>
            )}
          </ResponsiveContainer>
        </div>

        {/* Pulse band */}
        <div className="mt-4 grid gap-3 border-t border-border pt-4 md:grid-cols-2 xl:grid-cols-4">
          <TiltCard max={5}>
          <Link href="/calendar" className="group flex h-full items-center gap-3 rounded-xl border border-border bg-surface-2/40 p-3 transition-colors hover:border-border-strong hover:bg-surface-2">
            <MiniRing value={tonight.occupancy} color={tonight.occupancy >= 80 ? "var(--color-positive-500)" : tonight.occupancy >= 50 ? "var(--color-primary)" : "var(--color-warning-500)"}>
              {Math.round(tonight.occupancy)}%
            </MiniRing>
            <div className="min-w-0">
              <p className="eyebrow">Tonight</p>
              <p className="text-sm font-semibold">
                {tonight.occupied + tonight.reserved}/{tonight.total} occupied
              </p>
              <p className="mt-0.5 flex items-center gap-2 text-2xs text-fg-muted">
                <span className="flex items-center gap-0.5"><LogIn className="size-3 text-positive-600" /> {ops.arriving.length}</span>
                <span className="flex items-center gap-0.5"><LogOut className="size-3 text-warning-600" /> {ops.departing.length}</span>
                <span className="flex items-center gap-0.5"><Users className="size-3 text-info-600" /> {ops.inHouse.length}</span>
              </p>
            </div>
          </Link>
          </TiltCard>

          <TiltCard max={5}>
          <Link href="/payments" className="group block h-full rounded-xl border border-border bg-surface-2/40 p-3 transition-colors hover:border-border-strong hover:bg-surface-2">
            <p className="eyebrow">Money flow</p>
            <div className="mt-2">
              <Segmented total={Math.max(1, hero.paid + hero.expected + hero.outstanding)} parts={[{ key: "paid", value: hero.paid, color: "var(--color-positive-500)", label: "Collected" }, { key: "expected", value: hero.expected, color: "var(--color-primary)", label: "Expected" }, { key: "outstanding", value: hero.outstanding, color: "var(--color-warning-500)", label: "Outstanding" }]} />
            </div>
            <div className="mt-2 grid grid-cols-3 gap-1 text-2xs">
              <span><span className="mr-1 inline-block size-1.5 rounded-full bg-positive-500" />Collected<br /><b className="tabular text-fg">{money(hero.paid)}</b></span>
              <span><span className="mr-1 inline-block size-1.5 rounded-full bg-primary" />Expected<br /><b className="tabular text-fg">{money(hero.expected)}</b></span>
              <span><span className="mr-1 inline-block size-1.5 rounded-full bg-warning-500" />Due<br /><b className="tabular text-fg">{money(hero.outstanding)}</b></span>
            </div>
          </Link>
          </TiltCard>

          <TiltCard max={5}>
          <Link href="/reports?type=reservations" className="group block h-full rounded-xl border border-border bg-surface-2/40 p-3 transition-colors hover:border-border-strong hover:bg-surface-2">
            <p className="eyebrow">Channels</p>
            <div className="mt-2">
              <Segmented total={sourceTotal} parts={sources.map((s) => ({ key: s.name, value: s.revenue, color: s.color, label: s.name }))} />
            </div>
            <ul className="mt-2 space-y-0.5 text-2xs">
              {sources.slice(0, 3).map((s) => (
                <li key={s.name} className="flex items-center justify-between gap-2">
                  <span className="flex items-center gap-1 truncate text-fg-muted"><span className="size-1.5 shrink-0 rounded-full" style={{ background: s.color }} />{s.name}</span>
                  <span className="tabular text-fg">{sourceTotal ? Math.round((s.revenue / sourceTotal) * 100) : 0}%</span>
                </li>
              ))}
              {sources.length === 0 ? <li className="text-fg-subtle">No bookings in this period.</li> : null}
            </ul>
          </Link>
          </TiltCard>

          <TiltCard max={5}>
          <div className="h-full rounded-xl border border-border bg-surface-2/40 p-3">
            <p className="eyebrow">Best · weakest</p>
            {best && weakest ? (
              <ul className="mt-2 space-y-2 text-2xs">
                {[best, weakest].map((d, i) => (
                  <li key={i}>
                    <div className="flex items-center justify-between gap-2">
                      <span className="truncate text-fg-muted">{i === 0 ? "Best" : "Weakest"} · {d.label}</span>
                      <span className="tabular font-semibold text-fg">{money(d.revenue)}</span>
                    </div>
                    <div className="mt-1 h-1.5 overflow-hidden rounded-full bg-surface-3">
                      <motion.div className={cn("h-full rounded-full", i === 0 ? "bg-positive-500" : "bg-warning-500")} initial={{ width: 0 }} animate={{ width: `${(d.revenue / maxRev) * 100}%` }} transition={{ duration: 0.9, ease: [0.16, 1, 0.3, 1], delay: 0.1 * i }} />
                    </div>
                  </li>
                ))}
              </ul>
            ) : (
              <p className="mt-2 text-2xs text-fg-subtle">Not enough data yet.</p>
            )}
          </div>
          </TiltCard>
        </div>
      </CardContent>
    </Card>
  );
}

export { BarChart };
