"use client";

import type { ReactElement } from "react";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Bar, BarChart, CartesianGrid, Cell, XAxis, YAxis } from "recharts";

import {
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart";
import { signedMoneyClass } from "@/lib/admin-signed-money";
import { cn } from "@/lib/utils";
import { buildTrendChartConfig, DASHBOARD_CHART_COLORS } from "@/modules/dashboard/dashboard-chart-config";
import { DashboardChartEmpty } from "@/modules/dashboard/dashboard-chart-empty";
import type { AdminDashboardAnalyticsPlayRow } from "@/types/api/admin-dashboard-analytics";
import type { AdminReportDailyProfitRow } from "@/types/api/admin-reports";
import type { DashboardAnalyticsMetric } from "@/types/api/admin-dashboard-analytics";

type MoneyFormatter = (minor: number, currency: string | null) => string;

function playMetricValue(row: AdminDashboardAnalyticsPlayRow, metric: DashboardAnalyticsMetric): number {
  switch (metric) {
    case "bet":
      return row.total_bet_minor;
    case "payout":
      return row.total_payout_minor;
    case "profit":
      return row.approx_house_gross_minor;
    default:
      return row.total_bet_minor;
  }
}

function metricBarFill(metric: DashboardAnalyticsMetric, value: number): string {
  if (metric === "payout") {
    return DASHBOARD_CHART_COLORS.rose;
  }
  if (metric === "profit") {
    return value >= 0 ? DASHBOARD_CHART_COLORS.success : DASHBOARD_CHART_COLORS.warning;
  }
  return DASHBOARD_CHART_COLORS.primary;
}

export function DailyTrendChart({
  series,
  metric,
  formatMoney,
  currency,
}: {
  series: AdminReportDailyProfitRow[];
  metric: DashboardAnalyticsMetric;
  formatMoney: MoneyFormatter;
  currency: string | null;
}): ReactElement {
  const { t } = useTranslation("dashboard");

  const chartConfig = useMemo(
    () =>
      buildTrendChartConfig({
        bet: t("chartLegend.bet"),
        payout: t("chartLegend.payout"),
        profit: t("chartLegend.profit"),
      }),
    [t],
  );

  const chartData = useMemo(
    () =>
      series.map((day) => ({
        date: day.business_date.slice(5),
        fullDate: day.business_date,
        bet: day.total_bet_minor,
        payout: day.total_payout_minor,
        profit: day.approx_house_gross_minor,
        profitAbs: Math.abs(day.approx_house_gross_minor),
      })),
    [series],
  );

  if (series.length === 0) {
    return <DashboardChartEmpty />;
  }

  const plotHeight = series.length <= 7 ? 240 : series.length <= 14 ? 260 : 280;

  if (metric === "overview") {
    return (
      <ChartContainer
        config={chartConfig}
        className="aspect-auto w-full"
        style={{ height: plotHeight }}
      >
        <BarChart accessibilityLayer data={chartData} margin={{ top: 8, right: 8, bottom: 0, left: 8 }}>
          <CartesianGrid vertical={false} strokeDasharray="3 3" />
          <XAxis
            dataKey="date"
            tickLine={false}
            axisLine={false}
            tickMargin={8}
            interval={series.length > 14 ? Math.ceil(series.length / 7) - 1 : 0}
          />
          <ChartTooltip
            content={
              <ChartTooltipContent
                labelFormatter={(_, payload) => {
                  const row = payload?.[0]?.payload as { fullDate?: string } | undefined;
                  return row?.fullDate ?? "";
                }}
                formatter={(value, name, item) => {
                  if (name === "profit") {
                    const row = item?.payload as { profit?: number } | undefined;
                    return formatMoney(row?.profit ?? Number(value), currency);
                  }
                  return formatMoney(Number(value), currency);
                }}
              />
            }
          />
          <Bar dataKey="bet" fill="var(--color-bet)" radius={[4, 4, 0, 0]} />
          <Bar dataKey="payout" fill="var(--color-payout)" radius={[4, 4, 0, 0]} />
          <Bar dataKey="profitAbs" name="profit" fill="var(--color-profit)" radius={[4, 4, 0, 0]} />
          <ChartLegend content={<ChartLegendContent />} />
        </BarChart>
      </ChartContainer>
    );
  }

  const activeKey = metric === "bet" ? "bet" : metric === "payout" ? "payout" : "profitAbs";
  const dataKey = metric === "profit" ? "profitAbs" : activeKey;

  return (
    <ChartContainer
      config={chartConfig}
      className="aspect-auto w-full"
      style={{ height: plotHeight }}
    >
      <BarChart accessibilityLayer data={chartData} margin={{ top: 8, right: 8, bottom: 0, left: 8 }}>
        <CartesianGrid vertical={false} strokeDasharray="3 3" />
        <XAxis
          dataKey="date"
          tickLine={false}
          axisLine={false}
          tickMargin={8}
          interval={series.length > 14 ? Math.ceil(series.length / 7) - 1 : 0}
        />
        <ChartTooltip
          content={
            <ChartTooltipContent
              labelFormatter={(_, payload) => {
                const row = payload?.[0]?.payload as { fullDate?: string } | undefined;
                return row?.fullDate ?? "";
              }}
              formatter={(value) => formatMoney(Number(value), currency)}
            />
          }
        />
        <Bar dataKey={dataKey} radius={[4, 4, 0, 0]}>
          {chartData.map((row) => (
            <Cell
              key={row.fullDate}
              fill={metricBarFill(metric, row.profit)}
            />
          ))}
        </Bar>
      </BarChart>
    </ChartContainer>
  );
}

export function PlayBreakdownChart({
  rows,
  metric,
  formatMoney,
  currency,
  playLabel,
  compact = false,
}: {
  rows: AdminDashboardAnalyticsPlayRow[];
  metric: DashboardAnalyticsMetric;
  formatMoney: MoneyFormatter;
  currency: string | null;
  playLabel: (code: string, dimension: number) => string;
  compact?: boolean;
}): ReactElement {
  const { t } = useTranslation("dashboard");
  const activeMetric = metric === "overview" ? "bet" : metric;

  const chartConfig = useMemo(
    () =>
      buildTrendChartConfig({
        bet: t("chartLegend.bet"),
        payout: t("chartLegend.payout"),
        profit: t("chartLegend.profit"),
      }),
    [t],
  );

  const chartData = useMemo(
    () =>
      rows.map((row) => {
        const value = playMetricValue(row, activeMetric);
        return {
          id: `${row.play_code}-${row.dimension}`,
          label: playLabel(row.play_code, row.dimension),
          value: Math.abs(value),
          signed: value,
          payout: row.total_payout_minor,
          profit: row.approx_house_gross_minor,
          fill: metricBarFill(activeMetric, value),
        };
      }),
    [rows, activeMetric, playLabel],
  );

  if (rows.length === 0) {
    return <DashboardChartEmpty message={t("analytics.noPlayData")} />;
  }

  const chartHeight = compact
    ? Math.max(160, rows.length * 32 + 24)
    : Math.min(480, Math.max(180, rows.length * 36 + 48));

  return (
    <ChartContainer
      config={chartConfig}
      className="aspect-auto w-full min-w-0"
      style={{ height: chartHeight }}
    >
      <BarChart
        accessibilityLayer
        layout="vertical"
        data={chartData}
        margin={{ top: 4, right: 8, bottom: 4, left: 0 }}
      >
        <XAxis type="number" hide />
        <ChartTooltip
          content={
            <ChartTooltipContent
              labelFormatter={(_, payload) => {
                const row = payload?.[0]?.payload as { label?: string } | undefined;
                return row?.label ?? "";
              }}
              formatter={(value, _name, item) => {
                const row = item.payload as { signed: number; payout: number; profit: number };
                if (metric === "overview") {
                  return (
                    <span className="font-mono tabular-nums">
                      {formatMoney(row.signed, currency)} · {t("playBreakdownHint", {
                        payout: formatMoney(row.payout, currency),
                        profit: formatMoney(row.profit, currency),
                      })}
                    </span>
                  );
                }
                return formatMoney(row.signed, currency);
              }}
            />
          }
        />
        <Bar dataKey="value" radius={4} barSize={compact ? 12 : 14}>
          {chartData.map((entry) => (
            <Cell key={entry.id} fill={entry.fill} />
          ))}
        </Bar>
        <YAxis
          type="category"
          dataKey="label"
          width={compact ? 76 : 100}
          tickLine={false}
          axisLine={false}
          tick={{ fontSize: 10 }}
          tickFormatter={(value) =>
            typeof value === "string" && value.length > 10 ? `${value.slice(0, 10)}…` : String(value)
          }
        />
      </BarChart>
    </ChartContainer>
  );
}

export function PeriodCompareStrip({
  series,
  formatMoney,
  currency,
}: {
  series: AdminReportDailyProfitRow[];
  formatMoney: MoneyFormatter;
  currency: string | null;
}): ReactElement {
  const { t } = useTranslation("dashboard");
  const totalBet = series.reduce((s, d) => s + d.total_bet_minor, 0);
  const totalPayout = series.reduce((s, d) => s + d.total_payout_minor, 0);
  const totalProfit = series.reduce((s, d) => s + d.approx_house_gross_minor, 0);
  const maxAbs = Math.max(Math.abs(totalBet), Math.abs(totalPayout), Math.abs(totalProfit), 1);
  const payoutRate = totalBet > 0 ? (totalPayout / totalBet) * 100 : 0;
  const profitRate = totalBet > 0 ? (totalProfit / totalBet) * 100 : 0;

  const rows = [
    {
      key: "bet",
      label: t("chartLegend.bet"),
      value: totalBet,
      pctText: "100%",
      width: (Math.abs(totalBet) / maxAbs) * 100,
      fill: "var(--chart-1)",
    },
    {
      key: "payout",
      label: t("chartLegend.payout"),
      value: totalPayout,
      pctText: `${payoutRate.toFixed(1)}%`,
      width: (Math.abs(totalPayout) / maxAbs) * 100,
      fill: "var(--chart-5)",
    },
    {
      key: "profit",
      label: t("chartLegend.profit"),
      value: totalProfit,
      pctText: `${profitRate >= 0 ? "+" : ""}${profitRate.toFixed(1)}%`,
      width: (Math.abs(totalProfit) / maxAbs) * 100,
      fill: totalProfit >= 0 ? "var(--chart-2)" : DASHBOARD_CHART_COLORS.warning,
    },
  ] as const;

  return (
    <div className="grid gap-4">
      {rows.map((row) => (
        <div key={row.key} className="rounded-lg border border-border/60 bg-muted/20 px-3 py-3">
          <div className="mb-2 flex items-center justify-between gap-2">
            <span className="text-sm font-medium text-foreground">{row.label}</span>
            <span className="text-xs tabular-nums text-muted-foreground">{row.pctText}</span>
          </div>
          <div
            className={cn(
              "mb-1 text-sm font-semibold tabular-nums",
              row.key === "profit" ? signedMoneyClass(row.value, true) : undefined,
            )}
          >
            {formatMoney(row.value, currency)}
          </div>
          <div className="h-2 overflow-hidden rounded-full bg-muted">
            <div
              className="h-full rounded-full transition-[width] duration-500"
              style={{ width: `${Math.max(2, row.width)}%`, background: row.fill }}
            />
          </div>
        </div>
      ))}
    </div>
  );
}
