"use client";

import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Button, Spinner } from "@heroui/react";
import Link from "next/link";
import {
  Thunderbolt,
  CreditCard,
  ChartColumn,
  TagDollar,
  ArrowRotateRight,
  TriangleExclamation,
} from "@gravity-ui/icons";
import { AreaChart } from "@tremor/react";
import dayjs from "@/lib/dayjs";
import { useSession } from "@/lib/auth-client";
import {
  api,
  type Stats,
  type UserStats,
  type Transaction,
  type ChargePoint,
  type ChartRange,
  type ChartDataPoint,
} from "@/lib/api";
import { BanknoteArrowDown, EvCharger, Plug, Users } from "lucide-react";
import MetricIndicator from "@/components/metric-indicator";

// ── Helpers ────────────────────────────────────────────────────────────────

function timeAgo(dateStr: string | null | undefined): string {
  if (!dateStr) return "—";
  return dayjs(dateStr).fromNow();
}

function cpOnline(cp: ChargePoint): boolean {
  if (cp.transportStatus !== "online" || !cp.lastHeartbeatAt) return false;
  return dayjs().diff(dayjs(cp.lastHeartbeatAt), "second") < 120;
}

// ── StatCard ───────────────────────────────────────────────────────────────

type CardColor = "accent" | "success" | "warning" | "default";

const colorStyles: Record<CardColor, { border: string; bg: string; icon: string }> = {
  accent: { border: "border-accent", bg: "bg-accent/10", icon: "text-accent" },
  success: { border: "border-success", bg: "bg-success/10", icon: "text-success" },
  warning: { border: "border-warning", bg: "bg-warning/10", icon: "text-warning" },
  default: { border: "border-border", bg: "bg-default", icon: "text-muted" },
};

function StatusDot({ color }: { color: "success" | "warning" | "muted" }) {
  const cls =
    color === "success" ? "bg-success" : color === "warning" ? "bg-warning" : "bg-muted/40";
  return <span className={`inline-block h-1.5 w-1.5 shrink-0 rounded-full ${cls}`} />;
}

function StatCard({
  title,
  value,
  footer,
  icon: Icon,
  color = "default",
}: {
  title: string;
  value: string | number;
  footer?: React.ReactNode;
  icon?: React.ComponentType<{ className?: string }>;
  color?: CardColor;
}) {
  const s = colorStyles[color];
  return (
    <MetricIndicator
      title={title}
      value={value}
      color={s.border}
      valueClassName="text-3xl font-bold tabular-nums leading-none text-foreground"
      icon={
        Icon ? (
          <div className={`flex size-9 shrink-0 items-center justify-center rounded-xl ${s.bg}`}>
            <Icon className={`size-4.5 ${s.icon}`} />
          </div>
        ) : undefined
      }
      footer={footer}
    />
  );
}

// ── Panel wrapper ──────────────────────────────────────────────────────────

function Panel({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <div className="rounded-xl border border-border bg-surface-secondary overflow-hidden">
      <div className="border-b border-border px-5 py-3.5">
        <p className="text-sm font-semibold text-foreground">{title}</p>
      </div>
      {children}
    </div>
  );
}

// ── TrendChart ─────────────────────────────────────────────────────────────

function formatBucket(bucket: string, range: ChartRange): string {
  const d = dayjs(bucket);
  return range === "24h" ? d.format("HH:mm") : d.format("MM/DD");
}

const RANGES: { label: string; value: ChartRange }[] = [
  { label: "24 小时", value: "24h" },
  { label: "7 天", value: "7d" },
  { label: "30 天", value: "30d" },
];

type ChartView = "economy" | "activity";

const SERIES_CONFIG = {
  revenue: {
    color: "sky" as const,
    label: "营收",
    unit: "¥",
    fmt: (v: number) => (v === 0 ? "¥0" : `¥${v.toFixed(v < 10 ? 2 : 1)}`),
  },
  energyKwh: {
    color: "emerald" as const,
    label: "充电量",
    unit: "kWh",
    fmt: (v: number) => (v === 0 ? "0 kWh" : `${v.toFixed(v < 10 ? 2 : 1)} kWh`),
  },
  transactions: {
    color: "violet" as const,
    label: "充电次数",
    unit: "次",
    fmt: (v: number) => `${v} 次`,
  },
  utilizationPct: {
    color: "amber" as const,
    label: "利用率",
    unit: "%",
    fmt: (v: number) => `${v.toFixed(1)}%`,
  },
} as const;

const VIEW_SERIES: Record<ChartView, (keyof typeof SERIES_CONFIG)[]> = {
  economy: ["revenue", "energyKwh"],
  activity: ["transactions", "utilizationPct"],
};

function TrendChart() {
  const [range, setRange] = useState<ChartRange>("7d");
  const [view, setView] = useState<ChartView>("economy");
  const [hidden, setHidden] = useState<Set<string>>(new Set());

  const toggle = (key: string) =>
    setHidden((prev) => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key);
      else next.add(key);
      return next;
    });

  const switchView = (v: ChartView) => {
    setView(v);
    setHidden(new Set());
  };

  const allSeriesForView = VIEW_SERIES[view];
  const visibleSeries = allSeriesForView.filter((k) => !hidden.has(k));
  const visibleColors = visibleSeries.map((k) => SERIES_CONFIG[k].color);

  const { data, isPending } = useQuery<ChartDataPoint[]>({
    queryKey: ["stats-chart", range],
    queryFn: () => api.stats.chart(range),
    staleTime: 60_000,
  });

  return (
    <div className="rounded-xl border border-border bg-surface-secondary overflow-hidden">
      {/* Header */}
      <div className="flex flex-wrap items-center justify-between gap-2 border-b border-border px-5 py-3.5">
        {/* View toggle */}
        <div className="flex gap-1">
          {(["economy", "activity"] as ChartView[]).map((v) => (
            <button
              key={v}
              onClick={() => switchView(v)}
              className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${
                view === v
                  ? "bg-accent-soft text-accent"
                  : "text-muted hover:bg-default hover:text-foreground"
              }`}
            >
              {v === "economy" ? "营收 & 电量" : "次数 & 利用率"}
            </button>
          ))}
        </div>
        {/* Range toggle */}
        <div className="flex gap-1">
          {RANGES.map((r) => (
            <button
              key={r.value}
              onClick={() => setRange(r.value)}
              className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${
                range === r.value
                  ? "bg-accent text-white"
                  : "text-muted hover:bg-default hover:text-foreground"
              }`}
            >
              {r.label}
            </button>
          ))}
        </div>
      </div>

      {/* Chart */}
      <div className="px-4 py-4">
        {isPending ? (
          <div className="flex h-56 items-center justify-center">
            <Spinner />
          </div>
        ) : (
          <AreaChart
            data={(data ?? []).map((p) => ({ ...p, label: formatBucket(p.bucket, range) }))}
            index="label"
            categories={visibleSeries}
            colors={visibleColors}
            valueFormatter={(v) => `${v}`}
            customTooltip={(props) => {
              if (!props.active || !props.payload?.length) return null;
              return (
                <div className="rounded-lg border border-border bg-overlay px-3 py-2 shadow-md text-xs">
                  <p className="mb-1.5 font-semibold text-foreground">{props.label}</p>
                  {props.payload.map((entry) => {
                    const key = entry.dataKey as string;
                    const cfg = SERIES_CONFIG[key as keyof typeof SERIES_CONFIG];
                    if (!cfg) return null;
                    return (
                      <div key={key} className="flex items-center gap-2">
                        <span className={`inline-block h-2 w-2 rounded-full bg-${cfg.color}-500`} />
                        <span className="text-muted">{cfg.label}</span>
                        <span className="ml-auto font-medium text-foreground">
                          {cfg.fmt(entry.value as number)}
                        </span>
                      </div>
                    );
                  })}
                </div>
              );
            }}
            showLegend={false}
            showGridLines={true}
            showYAxis={true}
            showXAxis={true}
            curveType="monotone"
            showAnimation
            className="h-56 text-sm"
          />
        )}
        {/* Legend */}
        <div className="mt-2 flex items-center gap-2 px-1">
          {allSeriesForView.map((key) => {
            const cfg = SERIES_CONFIG[key];
            return (
              <button
                key={key}
                onClick={() => toggle(key)}
                className={`flex items-center gap-1.5 rounded px-1.5 py-0.5 text-xs transition-opacity select-none hover:opacity-100 ${
                  hidden.has(key) ? "opacity-35" : "opacity-100"
                }`}
              >
                <span className={`inline-block h-2 w-2 rounded-full bg-${cfg.color}-500`} />
                <span className="text-muted">
                  {cfg.label}（{cfg.unit}）
                </span>
              </button>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ── RecentTransactions ────────────────────────────────────────────────────

function RecentTransactions({ txns, isAdmin = false }: { txns: Transaction[]; isAdmin?: boolean }) {
  if (txns.length === 0) {
    return <div className="py-8 text-center text-sm text-muted">暂无充电记录</div>;
  }
  return (
    <ul className="divide-y divide-border">
      {txns.map((tx) => {
        const active = !tx.stopTimestamp;
        const kwh =
          tx.energyWh != null ? (tx.energyWh / 1000).toFixed(2) : active ? "充电中…" : "—";
        const amount =
          tx.chargeAmount != null && tx.chargeAmount > 0
            ? `¥${(tx.chargeAmount / 100).toFixed(2)}`
            : active
              ? "—"
              : "免费";
        return (
          <li key={tx.id} className="flex items-center gap-3 px-5 py-3">
            <span
              className={`flex size-7 shrink-0 items-center justify-center rounded-full ${active ? "bg-warning-soft" : "bg-success/10"}`}
            >
              <BanknoteArrowDown
                className={`size-3.5 ${active ? "text-warning" : "text-success"}`}
              />
            </span>
            <div className="min-w-0 flex-1">
              <p className="truncate text-sm font-medium text-foreground">
                {tx.chargePointDeviceName ?? tx.chargePointIdentifier ?? "—"}
                {tx.connectorNumber != null && (
                  <span className="ml-1 text-xs text-muted">#{tx.connectorNumber}</span>
                )}
                {isAdmin && tx.chargePointDeviceName && tx.chargePointIdentifier && (
                  <span className="ml-1 font-mono text-xs text-muted">
                    ({tx.chargePointIdentifier})
                  </span>
                )}
              </p>
              <p className="text-xs text-muted">
                {tx.idTag}
                {tx.idTagUserId && (
                  <>
                    <span className="mx-1">·</span>
                    {tx.idTagUserName ?? tx.idTagUserId}
                    <span className="ml-1 opacity-50">({tx.idTagUserId.slice(0, 8)})</span>
                  </>
                )}
              </p>
            </div>
            <div className="shrink-0 text-right">
              <p className="text-sm font-medium tabular-nums text-foreground">
                {kwh}
                <span className="text-xs"> kWh</span>
              </p>
              <p className="text-xs text-muted">{amount}</p>
            </div>
            <div className="w-16 shrink-0 text-right">
              <p className="text-xs text-muted">{timeAgo(tx.startTimestamp)}</p>
            </div>
          </li>
        );
      })}
    </ul>
  );
}

// ── ChargePointStatus ─────────────────────────────────────────────────────

function ChargePointStatus({ cps, isAdmin }: { cps: ChargePoint[]; isAdmin: boolean }) {
  if (cps.length === 0) {
    return <div className="py-8 text-center text-sm text-muted">暂无充电桩</div>;
  }
  return (
    <ul className="divide-y divide-border">
      {cps.map((cp) => {
        const online = cpOnline(cp);
        const chargingCount = cp.connectors.filter((c) => c.status === "Charging").length;
        const availableCount = cp.connectors.filter((c) => c.status === "Available").length;
        const faultedCount = cp.connectors.filter((c) => c.status === "Faulted").length;
        return (
          <li key={cp.id}>
            <Link
              href={`/dashboard/charge-points/${cp.id}`}
              className="flex items-center gap-3 px-5 py-3 transition-colors hover:bg-surface-hover"
            >
              <span
                className={`mt-0.5 h-2 w-2 shrink-0 rounded-full ${online ? "bg-success" : "bg-muted/40"}`}
              />
              <div className="min-w-0 flex-1">
                <p className="truncate text-sm font-medium text-foreground">
                  {cp.deviceName ?? cp.chargePointIdentifier}
                </p>
                {isAdmin && cp.deviceName && (
                  <p className="font-mono text-xs text-muted">{cp.chargePointIdentifier}</p>
                )}
                {!(isAdmin && cp.deviceName) && (
                  <p className="text-xs text-muted">
                    {cp.chargePointModel ?? cp.chargePointVendor ?? "未知型号"}
                  </p>
                )}
              </div>
              <div className="shrink-0 text-right">
                {online ? (
                  <div className="flex items-center gap-2">
                    {/* Charge point status */}
                    {cp.chargePointStatus === "Faulted" && (
                      <div className="flex justify-end">
                        <div className="flex items-center gap-1 rounded-md bg-danger/10 px-2 py-1">
                          <TriangleExclamation className="size-3 text-danger" />
                          <span className="text-xs font-medium text-danger">整桩故障</span>
                        </div>
                      </div>
                    )}
                    {/* Status summary */}
                    <div className="flex justify-end gap-2 text-xs">
                      {faultedCount > 0 && (
                        <div className="flex items-center gap-1">
                          <TriangleExclamation className="size-3 text-danger" />
                          <span className="font-medium text-danger">{faultedCount}</span>
                        </div>
                      )}
                      {chargingCount > 0 && (
                        <div className="flex items-center gap-1">
                          <Thunderbolt className="size-3 text-warning" />
                          <span className="font-medium text-warning">{chargingCount}</span>
                        </div>
                      )}
                      <div className="flex items-center gap-1">
                        <Plug className="size-3 text-accent" />
                        <span className="text-muted">{availableCount}</span>
                      </div>
                    </div>
                  </div>
                ) : (
                  <div className="text-xs text-muted">离线</div>
                )}
              </div>
            </Link>
          </li>
        );
      })}
    </ul>
  );
}

// ── Page ───────────────────────────────────────────────────────────────────

export default function DashboardPage() {
  const { data: sessionData, isPending } = useSession();
  const isAdmin = sessionData?.user?.role === "admin";

  const {
    data,
    isPending: queryPending,
    isFetching: refreshing,
    refetch,
  } = useQuery({
    queryKey: ["dashboard", isAdmin],
    queryFn: async () => {
      const [statsRes, txRes, cpsData] = await Promise.all([
        api.stats.get(),
        api.transactions.list({ limit: 6 }),
        isAdmin ? api.chargePoints.list() : Promise.resolve([] as ChargePoint[]),
      ]);
      return { stats: statsRes, txns: txRes.data, cps: cpsData };
    },
    refetchInterval: 3_000,
    enabled: !isPending,
  });

  if (isPending || queryPending) {
    return (
      <div className="space-y-6">
        <div>
          <h1 className="text-xl font-semibold text-foreground">概览</h1>
          <p className="mt-0.5 text-sm text-muted">加载中…</p>
        </div>
        <div className="flex justify-center py-16">
          <Spinner />
        </div>
      </div>
    );
  }

  // ── Admin view ────────────────────────────────────────────────────────────

  if (isAdmin) {
    const s = data?.stats as Stats | undefined;
    const todayKwh = s ? (s.todayEnergyWh / 1000).toFixed(1) : "—";
    const todayRevenue = s ? `¥${(s.todayRevenue / 100).toFixed(2)}` : "—";
    const offlineCount = (s?.totalChargePoints ?? 0) - (s?.onlineChargePoints ?? 0);

    return (
      <div className="space-y-6">
        <div className="flex items-start justify-between gap-3">
          <div>
            <h1 className="text-xl font-semibold text-foreground">概览</h1>
            <p className="mt-0.5 text-sm text-muted">实时运营状态</p>
          </div>
          <Button
            isIconOnly
            size="sm"
            variant="ghost"
            isDisabled={refreshing}
            onPress={() => refetch()}
            aria-label="刷新"
          >
            <ArrowRotateRight className={`size-4 ${refreshing ? "animate-spin" : ""}`} />
          </Button>
        </div>

        {/* Today's live metrics */}
        <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
          <StatCard
            title="今日充电次数"
            value={s?.todayTransactions ?? "—"}
            icon={ChartColumn}
            color="accent"
            footer={<span>当日 00:00 起累计</span>}
          />
          <StatCard
            title="今日充电量"
            value={`${todayKwh} kWh`}
            icon={Thunderbolt}
            color="accent"
            footer={<span>当日累计输出电能</span>}
          />
          <StatCard
            title="今日营收"
            value={todayRevenue}
            icon={TagDollar}
            color="success"
            footer={<span>已完成订单金额合计</span>}
          />
          <StatCard
            title="活跃充电"
            value={s?.activeTransactions ?? "—"}
            icon={Thunderbolt}
            color={s?.activeTransactions ? "warning" : "default"}
            footer={
              <>
                <StatusDot color={s?.activeTransactions ? "success" : "muted"} />
                <span className={s?.activeTransactions ? "font-medium text-success" : ""}>
                  {s?.activeTransactions ? "充电进行中" : "当前空闲"}
                </span>
              </>
            }
          />
        </div>

        {/* Infrastructure metrics */}
        <div className="grid grid-cols-3 gap-4">
          <StatCard
            title="充电桩总数"
            value={s?.totalChargePoints ?? "—"}
            icon={EvCharger}
            color="default"
            footer={
              <>
                <StatusDot color="success" />
                <span className="font-medium text-success">{s?.onlineChargePoints ?? 0} 在线</span>
                <span className="text-border">·</span>
                <span>{offlineCount} 离线</span>
              </>
            }
          />
          <StatCard
            title="储值卡总数"
            value={s?.totalIdTags ?? "—"}
            icon={CreditCard}
            color="default"
            footer={<span>已注册卡片总量</span>}
          />
          <StatCard
            title="注册用户"
            value={s?.totalUsers ?? "—"}
            icon={Users}
            color="default"
            footer={<span>系统用户总数</span>}
          />
        </div>

        {/* Trend chart */}
        {isAdmin && <TrendChart />}

        {/* Detail panels */}
        <div className="grid grid-cols-1 gap-4 lg:grid-cols-5">
          <div className="lg:col-span-2">
            <Panel title="充电桩状态">
              <ChargePointStatus cps={data?.cps ?? []} isAdmin={isAdmin} />
            </Panel>
          </div>
          <div className="lg:col-span-3">
            <Panel title="最近充电会话">
              <RecentTransactions txns={data?.txns ?? []} isAdmin={isAdmin} />
            </Panel>
          </div>
        </div>
      </div>
    );
  }

  // ── User view ─────────────────────────────────────────────────────────────

  const s = data?.stats as UserStats | undefined;
  const totalYuan = s ? (s.totalBalance / 100).toFixed(2) : "—";
  const todayKwh = s ? (s.todayEnergyWh / 1000).toFixed(2) : "—";

  return (
    <div className="space-y-6">
      <div className="flex items-start justify-between gap-3">
        <div>
          <h1 className="text-xl font-semibold text-foreground">概览</h1>
          <p className="mt-0.5 text-sm text-muted">
            {sessionData?.user?.name ?? sessionData?.user?.email} 的账户概览
          </p>
        </div>
        <Button
          isIconOnly
          size="sm"
          variant="ghost"
          isDisabled={refreshing}
          onPress={() => refetch()}
          aria-label="刷新"
        >
          <ArrowRotateRight className={`size-4 ${refreshing ? "animate-spin" : ""}`} />
        </Button>
      </div>

      <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
        <StatCard
          title="我的储值卡"
          value={s?.totalIdTags ?? "—"}
          icon={CreditCard}
          color="accent"
          footer={<span>已绑定的储值卡数量</span>}
        />
        <StatCard
          title="账户总余额"
          value={`¥${totalYuan}`}
          icon={TagDollar}
          color="success"
          footer={<span>所有储值卡余额合计</span>}
        />
        <StatCard
          title="今日充电量"
          value={`${todayKwh} kWh`}
          icon={Thunderbolt}
          color={s?.todayEnergyWh ? "warning" : "default"}
          footer={
            <>
              <StatusDot color={s?.activeTransactions ? "success" : "muted"} />
              <span className={s?.activeTransactions ? "font-medium text-success" : ""}>
                {s?.activeTransactions ? "充电中" : "当前空闲"}
              </span>
            </>
          }
        />
        <StatCard
          title="累计充电次数"
          value={s?.totalTransactions ?? "—"}
          icon={ChartColumn}
          color="default"
          footer={<span>今日 {s?.todayTransactions ?? 0} 次</span>}
        />
      </div>

      <Panel title="最近充电记录">
        <RecentTransactions txns={data?.txns ?? []} />
      </Panel>
    </div>
  );
}
