"use client";

import { lazy, Suspense, useEffect, useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { useLocale, useTranslations } from "next-intl";
import { Download, TrendingDown, TrendingUp } from "lucide-react";
import { apiGet, ApiClientError } from "@/lib/api/client";
import { useAuthStore } from "@/lib/stores/auth.store";
import { formatCurrency, formatNumber } from "@/lib/format";
import {
  aggregateByDate,
  branchComparisonPoints,
  buildRangeFromPreset,
  downloadReportsCsv,
  isoTodayTehran,
  percentChange,
  previousPeriod,
  revenueChartPoints,
  sumSnapshots,
  topProductsFromRange,
  type DailyReportSnapshot,
  type DateRangePreset,
  type ReportRange,
} from "@/lib/reports/analytics";
import { PageHeader } from "@/components/layout/page-header";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { LabeledField } from "@/components/ui/labeled-field";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { cn } from "@/lib/utils";
import { ReportsChartsFallback } from "@/components/reports/reports-charts-fallback";
import type { ReportsChartsProps } from "@/components/reports/reports-charts.types";

const LazyReportsCharts = lazy(() =>
  import("@/components/reports/reports-charts").then((m) => ({
    default: m.ReportsCharts,
  }))
);

type Branch = { id: string; name: string };

const OWNER_ROLES = new Set(["Owner", "Manager"]);
const MULTI_BRANCH_PLANS = new Set(["Pro", "Business", "Enterprise"]);

export function ReportsScreen() {
  const t = useTranslations("reports");
  const locale = useLocale();
  const rtl = locale === "fa" || locale === "ar";
  const numberLocale = locale === "en" ? "en-US" : "fa-IR";
  const cafeId = useAuthStore((s) => s.user?.cafeId);
  const role = useAuthStore((s) => s.user?.role);
  const planTier = useAuthStore((s) => s.user?.planTier ?? "Free");

  const [range, setRange] = useState<ReportRange>(() => buildRangeFromPreset("7d"));
  const [branchId, setBranchId] = useState<string | null>(null);
  const [planError, setPlanError] = useState<string | null>(null);

  const canViewAllBranches = OWNER_ROLES.has(role ?? "");

  const { data: branches = [] } = useQuery({
    queryKey: ["branches", cafeId],
    queryFn: () => apiGet<Branch[]>(`/api/cafes/${cafeId}/branches`),
    enabled: !!cafeId,
  });

  useEffect(() => {
    if (!canViewAllBranches && branchId === null && branches.length > 0) {
      setBranchId(branches[0]!.id);
    }
  }, [canViewAllBranches, branchId, branches]);

  const branchQuery = branchId ? `&branchId=${encodeURIComponent(branchId)}` : "";
  const rangeKey = `${range.from}_${range.to}_${branchId ?? "all"}`;

  const { data: snapshots = [], isLoading, isError, error } = useQuery({
    queryKey: ["reports-daily-range", cafeId, rangeKey],
    queryFn: async () => {
      setPlanError(null);
      return apiGet<DailyReportSnapshot[]>(
        `/api/cafes/${cafeId}/reports/daily/range?from=${range.from}&to=${range.to}${branchQuery}`
      );
    },
    enabled: !!cafeId && !!range.from && !!range.to,
    retry: false,
  });

  const prev = useMemo(
    () => previousPeriod(range.from, range.to),
    [range.from, range.to]
  );

  const { data: prevSnapshots = [] } = useQuery({
    queryKey: ["reports-daily-range-prev", cafeId, prev.from, prev.to, branchId],
    queryFn: () =>
      apiGet<DailyReportSnapshot[]>(
        `/api/cafes/${cafeId}/reports/daily/range?from=${prev.from}&to=${prev.to}${branchQuery}`
      ),
    enabled: !!cafeId,
  });

  useEffect(() => {
    if (isError && error instanceof ApiClientError && error.code === "PLAN_LIMIT_REACHED") {
      setPlanError(error.message);
    } else if (!isError) {
      setPlanError(null);
    }
  }, [isError, error]);

  const displayRows = useMemo(() => {
    if (branchId) return [...snapshots].sort((a, b) => a.date.localeCompare(b.date));
    return aggregateByDate(snapshots);
  }, [snapshots, branchId]);

  const prevRows = useMemo(() => {
    if (branchId) return prevSnapshots;
    return aggregateByDate(prevSnapshots);
  }, [prevSnapshots, branchId]);

  const totals = useMemo(() => sumSnapshots(displayRows), [displayRows]);
  const prevTotals = useMemo(() => sumSnapshots(prevRows), [prevRows]);

  const chartData = useMemo(
    () => revenueChartPoints(displayRows, locale, rtl),
    [displayRows, locale, rtl]
  );

  const pieData = useMemo(
    () => [
      { key: "cash", name: t("cash"), value: totals.cashRevenue, fill: "#0F6E56" },
      { key: "card", name: t("card"), value: totals.cardRevenue, fill: "#0C447C" },
      { key: "credit", name: t("credit"), value: totals.creditRevenue, fill: "#BA7517" },
    ].filter((d) => d.value > 0),
    [totals, t]
  );

  const topProducts = useMemo(
    () => topProductsFromRange(displayRows, 10),
    [displayRows]
  );

  const showBranchCompare =
    !branchId &&
    branches.length > 1 &&
    OWNER_ROLES.has(role ?? "") &&
    MULTI_BRANCH_PLANS.has(planTier);

  const branchCompareData = useMemo(() => {
    if (!showBranchCompare) return [];
    return branchComparisonPoints(snapshots, branches, locale, rtl);
  }, [showBranchCompare, snapshots, branches, locale, rtl]);

  const branchNameMap = useMemo(
    () => new Map(branches.map((b) => [b.id, b.name])),
    [branches]
  );

  const setPreset = (preset: DateRangePreset) => {
    setRange(buildRangeFromPreset(preset));
  };

  const handleExportCsv = () => {
    const sorted = [...snapshots].sort(
      (a, b) => a.date.localeCompare(b.date) || a.branchId.localeCompare(b.branchId)
    );
    downloadReportsCsv(
      sorted,
      branchNameMap,
      {
        date: t("csvDate"),
        branch: t("csvBranch"),
        totalRevenue: t("csvTotalRevenue"),
        totalOrders: t("csvTotalOrders"),
        avgOrderValue: t("csvAvgOrder"),
        cashRevenue: t("csvCash"),
        cardRevenue: t("csvCard"),
        creditRevenue: t("csvCredit"),
        netIncome: t("csvNetIncome"),
        totalVoids: t("csvVoids"),
        voidAmount: t("csvVoidAmount"),
        totalExpenses: t("csvExpenses"),
      },
      `meezi-reports-${range.from}_${range.to}.csv`
    );
  };

  if (!cafeId) return null;

  return (
    <div className="space-y-6 bg-[#f5f5f4] min-h-full -m-4 p-4 md:-m-6 md:p-6">
      <PageHeader
        title={t("title")}
        subtitle={t("subtitle")}
        action={
          <Button
            variant="outline"
            className="border-[#0F6E56]/40"
            onClick={handleExportCsv}
            disabled={snapshots.length === 0}
          >
            <Download className="ms-2 h-4 w-4" />
            {t("exportCsv")}
          </Button>
        }
      />

      <Card className="rounded-xl border border-border/80 bg-card">
        <CardContent className="flex flex-wrap items-end gap-4 pt-6">
          <div className="flex flex-wrap gap-2">
            {(["7d", "30d", "90d"] as const).map((preset) => (
              <Button
                key={preset}
                size="sm"
                variant={range.preset === preset ? "default" : "outline"}
                className={cn(
                  range.preset === preset && "bg-[#0F6E56] hover:bg-[#0d5e49]"
                )}
                onClick={() => setPreset(preset)}
              >
                {t(`preset.${preset}`)}
              </Button>
            ))}
          </div>

          <LabeledField label={t("fromDate")} htmlFor="report-from">
            <Input
              id="report-from"
              type="date"
              dir="ltr"
              className="w-40 text-end"
              value={range.from}
              max={range.to}
              onChange={(e) =>
                setRange((r) => ({ ...r, from: e.target.value, preset: "custom" }))
              }
            />
          </LabeledField>
          <LabeledField label={t("toDate")} htmlFor="report-to">
            <Input
              id="report-to"
              type="date"
              dir="ltr"
              className="w-40 text-end"
              value={range.to}
              min={range.from}
              max={isoTodayTehran()}
              onChange={(e) =>
                setRange((r) => ({ ...r, to: e.target.value, preset: "custom" }))
              }
            />
          </LabeledField>

          {branches.length > 0 ? (
            <LabeledField label={t("branch")} htmlFor="report-branch">
              <select
                id="report-branch"
                className="h-9 min-w-[10rem] rounded-md border border-input bg-background px-3 text-sm"
                value={branchId ?? ""}
                onChange={(e) => setBranchId(e.target.value || null)}
              >
                {canViewAllBranches ? (
                  <option value="">{t("allBranches")}</option>
                ) : null}
                {branches.map((b) => (
                  <option key={b.id} value={b.id}>
                    {b.name}
                  </option>
                ))}
              </select>
            </LabeledField>
          ) : null}
        </CardContent>
      </Card>

      {planError ? (
        <p className="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-[#BA7517]">
          {planError}
        </p>
      ) : null}

      <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
        <KpiCard
          title={t("kpiTotalRevenue")}
          value={isLoading ? "…" : formatCurrency(totals.totalRevenue, numberLocale)}
          change={percentChange(totals.totalRevenue, prevTotals.totalRevenue)}
          vsLabel={t("vsPrevious")}
          numberLocale={numberLocale}
        />
        <KpiCard
          title={t("kpiTotalOrders")}
          value={isLoading ? "…" : formatNumber(totals.totalOrders, numberLocale)}
          change={percentChange(totals.totalOrders, prevTotals.totalOrders)}
          vsLabel={t("vsPrevious")}
          numberLocale={numberLocale}
        />
        <KpiCard
          title={t("kpiAvgOrder")}
          value={isLoading ? "…" : formatCurrency(totals.avgOrderValue, numberLocale)}
          change={percentChange(totals.avgOrderValue, prevTotals.avgOrderValue)}
          vsLabel={t("vsPrevious")}
          numberLocale={numberLocale}
        />
        <KpiCard
          title={t("kpiNetIncome")}
          value={isLoading ? "…" : formatCurrency(totals.netIncome, numberLocale)}
          change={percentChange(totals.netIncome, prevTotals.netIncome)}
          vsLabel={t("vsPrevious")}
          numberLocale={numberLocale}
        />
        <KpiCard
          title={t("kpiTotalExpenses")}
          value={isLoading ? "…" : formatCurrency(totals.totalExpenses, numberLocale)}
          change={percentChange(totals.totalExpenses, prevTotals.totalExpenses)}
          vsLabel={t("vsPrevious")}
          numberLocale={numberLocale}
          valueClassName="text-[#BA7517]"
        />
      </div>

      <DeferredReportsCharts
        isLoading={isLoading}
        numberLocale={numberLocale}
        chartData={chartData}
        pieData={pieData}
        branchCompareData={branchCompareData}
        showBranchCompare={showBranchCompare}
        branches={branches}
      />

      <Card className="rounded-xl border border-border/80 bg-card">
        <CardHeader>
          <CardTitle className="text-base">{t("topProductsTitle")}</CardTitle>
        </CardHeader>
        <CardContent className="overflow-x-auto">
          <table className="w-full min-w-[24rem] text-sm">
            <thead>
              <tr className="border-b text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground">
                <th className="py-2 text-start">{t("colProduct")}</th>
                <th className="py-2 text-end">{t("colQuantity")}</th>
                <th className="py-2 text-end">{t("colRevenue")}</th>
              </tr>
            </thead>
            <tbody>
              {topProducts.length === 0 ? (
                <tr>
                  <td colSpan={3} className="py-4 text-muted-foreground">
                    {t("noData")}
                  </td>
                </tr>
              ) : (
                topProducts.map((p, idx) => (
                  <tr key={p.productId} className="border-b border-border/50">
                    <td className="py-2.5">
                      <span className="me-2 text-muted-foreground">
                        {formatNumber(idx + 1, numberLocale)}.
                      </span>
                      {p.name}
                    </td>
                    <td className="py-2.5 text-end tabular-nums">
                      {formatNumber(p.quantity, numberLocale)}
                    </td>
                    <td className="py-2.5 text-end font-medium text-[#0F6E56] tabular-nums">
                      {formatCurrency(p.revenue, numberLocale)}
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </CardContent>
      </Card>
    </div>
  );
}

function DeferredReportsCharts(props: ReportsChartsProps) {
  const [ready, setReady] = useState(false);

  useEffect(() => {
    const id =
      typeof requestIdleCallback !== "undefined"
        ? requestIdleCallback(() => setReady(true))
        : window.setTimeout(() => setReady(true), 0);
    return () => {
      if (typeof requestIdleCallback !== "undefined" && typeof id === "number") {
        cancelIdleCallback(id);
      } else {
        clearTimeout(id as number);
      }
    };
  }, []);

  if (!ready) {
    return <ReportsChartsFallback />;
  }

  return (
    <Suspense fallback={<ReportsChartsFallback />}>
      <LazyReportsCharts {...props} />
    </Suspense>
  );
}

function KpiCard({
  title,
  value,
  change,
  vsLabel,
  numberLocale,
  valueClassName,
}: {
  title: string;
  value: string;
  change: number | null;
  vsLabel: string;
  numberLocale: string;
  valueClassName?: string;
}) {
  const positive = change !== null && change >= 0;
  return (
    <Card className="rounded-xl border border-border/80 bg-card">
      <CardContent className="space-y-1 pt-5">
        <p className="text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground">
          {title}
        </p>
        <p className={cn("text-xl font-semibold text-foreground", valueClassName)}>{value}</p>
        {change !== null ? (
          <p
            className={cn(
              "flex items-center gap-1 text-xs",
              positive ? "text-[#0F6E56]" : "text-[#A32D2D]"
            )}
          >
            {positive ? (
              <TrendingUp className="h-3.5 w-3.5" />
            ) : (
              <TrendingDown className="h-3.5 w-3.5" />
            )}
            {formatNumber(Math.round(Math.abs(change) * 10) / 10, numberLocale)}% {vsLabel}
          </p>
        ) : null}
      </CardContent>
    </Card>
  );
}
