import { Link } from "@tanstack/react-router";
import { BarChart3, RefreshCw } from "lucide-react";
import { useMemo, useState } from "react";
import {
  CartesianGrid,
  Line,
  LineChart,
  ReferenceLine,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import {
  Gauge,
  GaugeIndicator,
  GaugeRange,
  GaugeTrack,
  GaugeValueText,
} from "@/components/ui/gauge";
import {
  useDailyMinMax,
  useDailyQuotes,
  useFetchQuotes,
  useQuoteHistory,
  useQuotes,
} from "@/lib/queries";
import { RelativeTime } from "@/lib/time";
import { cn } from "@/lib/utils";

const priceFormatter = new Intl.NumberFormat("es-AR", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
});

function formatDate(d: Date): string {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

function formatTime(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleTimeString("es-AR", { hour: "2-digit", minute: "2-digit" });
}

function formatShortDate(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleDateString("es-AR", {
    day: "2-digit",
    month: "2-digit",
  });
}

function getGaugeColor(percentage: number | null): string {
  if (percentage === null) return "text-muted-foreground";
  if (percentage >= 0.8) return "text-emerald-500";
  if (percentage >= 0.5) return "text-yellow-500";
  return "text-red-500";
}

function StatCard({
  label,
  buy,
  sell,
  buyDate,
  sellDate,
}: {
  label: string;
  buy: string | number;
  sell: string | number;
  buyDate?: string;
  sellDate?: string;
}) {
  return (
    <div className="rounded-lg border p-4">
      <p className="text-sm text-muted-foreground mb-2">{label}</p>
      <div className="space-y-1">
        <p className="text-sm">
          Compra:{" "}
          <span className="text-lg font-bold">
            ${priceFormatter.format(Number(buy))}
          </span>
          {buyDate && (
            <span className="text-[10px] text-muted-foreground ml-1.5">
              {formatShortDate(buyDate)}
            </span>
          )}
        </p>
        <p className="text-sm">
          Venta:{" "}
          <span className="text-lg font-bold">
            ${priceFormatter.format(Number(sell))}
          </span>
          {sellDate && (
            <span className="text-[10px] text-muted-foreground ml-1.5">
              {formatShortDate(sellDate)}
            </span>
          )}
        </p>
      </div>
    </div>
  );
}

type Period = "day" | "month";

export function BeloPage() {
  const [period, setPeriod] = useState<Period>("day");

  const now = new Date();
  const todayStr = formatDate(now);
  const firstOfMonth = formatDate(
    new Date(now.getFullYear(), now.getMonth(), 1),
  );

  const { data: quotes, isLoading: quotesLoading } = useQuotes();
  const { mutate: doFetchQuotes, isPending: fetchPending } = useFetchQuotes();
  const { data: dailyMinMax } = useDailyMinMax("BELO", todayStr, todayStr);
  const { data: monthlyMinMax } = useDailyMinMax(
    "BELO",
    firstOfMonth,
    todayStr,
  );
  const { data: history, isLoading: historyLoading } = useQuoteHistory(
    "BELO",
    todayStr,
    todayStr,
  );
  const { data: daily, isLoading: dailyLoading } = useDailyQuotes(
    "BELO",
    firstOfMonth,
    todayStr,
  );

  const belo = quotes?.find((q) => q.type === "BELO");
  const maxData = dailyMinMax?.[0];

  const currentBuy = belo ? Number(belo.buy) : 0;
  const currentSell = belo ? Number(belo.sell) : 0;
  const minBuy = maxData ? Number(maxData.minBuy) : 0;
  const maxBuy = maxData ? Number(maxData.maxBuy) : 0;
  const minSell = maxData ? Number(maxData.minSell) : 0;
  const maxSell = maxData ? Number(maxData.maxSell) : 0;

  const gaugeValue =
    currentBuy > 0 && maxBuy > minBuy ? Math.min(currentBuy, maxBuy) : null;

  const gaugePercentage = useMemo(() => {
    if (gaugeValue !== null && maxBuy > minBuy) {
      return (gaugeValue - minBuy) / (maxBuy - minBuy);
    }
    return null;
  }, [gaugeValue, minBuy, maxBuy]);

  const chartData = useMemo(() => {
    if (period === "day") {
      if (!history) return [];
      return history.map((h) => ({
        time: formatTime(h.timeStamp),
        buy: Number(h.buy),
        sell: Number(h.sell),
      }));
    }
    if (!daily) return [];
    return daily.map((d) => ({
      time: formatShortDate(d.date),
      buy: d.buy,
      sell: d.sell,
    }));
  }, [history, daily, period]);

  const yDomain = useMemo(() => {
    if (chartData.length === 0) return [0, 0];
    let min = Infinity;
    let max = -Infinity;
    for (const d of chartData) {
      if (d.buy < min) min = d.buy;
      if (d.sell < min) min = d.sell;
      if (d.buy > max) max = d.buy;
      if (d.sell > max) max = d.sell;
    }
    const range = max - min;
    return [min - range * 0.1, max + range * 0.1];
  }, [chartData]);

  const maxBuyValue = useMemo(() => {
    if (chartData.length === 0) return 0;
    let max = -Infinity;
    for (const d of chartData) {
      if (d.buy > max) max = d.buy;
    }
    return max;
  }, [chartData]);

  const maxSellValue = useMemo(() => {
    if (chartData.length === 0) return 0;
    let max = -Infinity;
    for (const d of chartData) {
      if (d.sell > max) max = d.sell;
    }
    return max;
  }, [chartData]);

  const monthlyMax = useMemo(() => {
    if (!monthlyMinMax || monthlyMinMax.length === 0) return null;

    let maxBuyEntry = monthlyMinMax[0];
    let maxSellEntry = monthlyMinMax[0];

    for (const d of monthlyMinMax) {
      if (d.maxBuy > maxBuyEntry.maxBuy) maxBuyEntry = d;
      if (d.maxSell > maxSellEntry.maxSell) maxSellEntry = d;
    }

    return {
      maxBuy: maxBuyEntry.maxBuy,
      maxBuyDate: maxBuyEntry.date,
      maxSell: maxSellEntry.maxSell,
      maxSellDate: maxSellEntry.date,
    };
  }, [monthlyMinMax]);

  const isFetching = quotesLoading || fetchPending;

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-semibold">BELO</h1>
        <div className="flex items-center gap-3">
          {belo && (
            <span className="text-xs text-muted-foreground">
              Últ. actualización: <RelativeTime date={belo.timeStamp} />
            </span>
          )}
          <Link
            to="/quotes/belo/analysis"
            className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
          >
            <BarChart3 className="h-4 w-4" />
            Análisis
          </Link>
          <button
            type="button"
            disabled={isFetching}
            onClick={() => doFetchQuotes()}
            className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors cursor-pointer"
          >
            <RefreshCw
              className={`h-4 w-4 ${isFetching ? "animate-spin" : ""}`}
            />
            Actualizar
          </button>
        </div>
      </div>

      <div className="grid gap-4 md:grid-cols-5">
        <StatCard label="Precio actual" buy={currentBuy} sell={currentSell} />
        <StatCard label="Mínimo del día" buy={minBuy} sell={minSell} />
        <StatCard label="Máximo del día" buy={maxBuy} sell={maxSell} />
        <StatCard
          label="Máximo del mes"
          buy={monthlyMax?.maxBuy ?? 0}
          sell={monthlyMax?.maxSell ?? 0}
          buyDate={monthlyMax?.maxBuyDate}
          sellDate={monthlyMax?.maxSellDate}
        />
        <div className="rounded-lg border p-4 flex flex-col items-center justify-center">
          <p className="text-xs text-muted-foreground mb-0.5">Avance</p>
          <Gauge
            value={gaugeValue}
            min={minBuy}
            max={maxBuy}
            size={80}
            thickness={6}
            startAngle={0}
            endAngle={360}
            getValueText={(v, m, mx) => {
              const pct =
                mx === m ? 100 : Math.round(((v - m) / (mx - m)) * 100);
              return `${pct}%`;
            }}
          >
            <GaugeIndicator>
              <GaugeTrack />
              <GaugeRange className={getGaugeColor(gaugePercentage)} />
            </GaugeIndicator>
            <GaugeValueText
              className={cn(
                getGaugeColor(gaugePercentage),
                "text-sm font-semibold",
              )}
            />
          </Gauge>
        </div>
      </div>

      <div className="rounded-lg border p-4">
        <div className="flex items-center justify-between mb-4">
          <h2 className="text-sm font-medium">Evolución del precio</h2>
          <div className="flex items-center gap-1 rounded-lg border p-0.5">
            <button
              type="button"
              onClick={() => setPeriod("day")}
              className={`px-3 py-1 text-xs rounded-md transition-colors cursor-pointer ${
                period === "day"
                  ? "bg-primary text-primary-foreground"
                  : "text-muted-foreground hover:text-foreground"
              }`}
            >
              Día
            </button>
            <button
              type="button"
              onClick={() => setPeriod("month")}
              className={`px-3 py-1 text-xs rounded-md transition-colors cursor-pointer ${
                period === "month"
                  ? "bg-primary text-primary-foreground"
                  : "text-muted-foreground hover:text-foreground"
              }`}
            >
              Mes
            </button>
          </div>
        </div>

        {(period === "day" ? historyLoading : dailyLoading) ? (
          <div className="flex items-center justify-center h-64 text-muted-foreground">
            Cargando...
          </div>
        ) : chartData.length === 0 ? (
          <div className="flex items-center justify-center h-64 text-muted-foreground">
            Sin datos para este período
          </div>
        ) : (
          <div className="h-64">
            <ResponsiveContainer width="100%" height="100%">
              <LineChart data={chartData}>
                <CartesianGrid
                  strokeDasharray="3 3"
                  className="stroke-border"
                />
                <XAxis
                  dataKey="time"
                  tick={{ fontSize: 11 }}
                  className="text-muted-foreground"
                  interval="preserveStartEnd"
                />
                <YAxis
                  tick={{ fontSize: 11 }}
                  className="text-muted-foreground"
                  tickFormatter={(v: number) => `$${priceFormatter.format(v)}`}
                  width={80}
                  domain={yDomain}
                />
                <Tooltip
                  // biome-ignore lint/suspicious/noExplicitAny: recharts types
                  formatter={(value: any) => [
                    `$${priceFormatter.format(Number(value))}`,
                  ]}
                  // biome-ignore lint/suspicious/noExplicitAny: recharts types
                  labelFormatter={(label: any) =>
                    period === "day" ? `Hora: ${label}` : `Fecha: ${label}`
                  }
                  contentStyle={{
                    backgroundColor: "var(--card)",
                    border: "1px solid var(--border)",
                    borderRadius: "var(--radius)",
                    fontSize: 13,
                  }}
                />
                <ReferenceLine
                  y={maxBuyValue}
                  stroke="var(--chart-1)"
                  strokeDasharray="4 4"
                  strokeWidth={1.5}
                  label={{
                    value: `Máx compra: $${priceFormatter.format(maxBuyValue)}`,
                    position: "right",
                    fontSize: 11,
                    fill: "var(--chart-1)",
                  }}
                />
                <ReferenceLine
                  y={maxSellValue}
                  stroke="var(--chart-2)"
                  strokeDasharray="4 4"
                  strokeWidth={1.5}
                  label={{
                    value: `Máx venta: $${priceFormatter.format(maxSellValue)}`,
                    position: "right",
                    fontSize: 11,
                    fill: "var(--chart-2)",
                  }}
                />
                <Line
                  type="monotone"
                  dataKey="buy"
                  name="Compra"
                  stroke="var(--chart-1)"
                  strokeWidth={2}
                  dot={false}
                  activeDot={{ r: 4 }}
                  isAnimationActive={false}
                />
                <Line
                  type="monotone"
                  dataKey="sell"
                  name="Venta"
                  stroke="var(--chart-2)"
                  strokeWidth={2}
                  dot={false}
                  activeDot={{ r: 4 }}
                  isAnimationActive={false}
                />
              </LineChart>
            </ResponsiveContainer>
          </div>
        )}

        <div className="flex items-center justify-center gap-4 mt-3">
          <div className="flex items-center gap-1.5">
            <span
              className="size-2.5 rounded-full"
              style={{ backgroundColor: "var(--chart-1)" }}
            />
            <span className="text-xs text-muted-foreground">Compra</span>
          </div>
          <div className="flex items-center gap-1.5">
            <span
              className="size-2.5 rounded-full"
              style={{ backgroundColor: "var(--chart-2)" }}
            />
            <span className="text-xs text-muted-foreground">Venta</span>
          </div>
        </div>
      </div>
    </div>
  );
}
