"use client";

import { useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import {
  ArrowUpRight,
  Bell,
  Clock,
  History,
  Pin,
  Receipt,
  Send,
  Tag,
  TrendingUp,
  Users,
  Wallet,
} from "lucide-react";
import { Container } from "@/components/common/Container";
import { Card, CardContent } from "@/components/common/Card";
import { ButtonLink } from "@/components/common/Button";
import { EmptyState } from "@/components/app/EmptyState";
import { KycStatusBanner } from "@/components/app/KycStatusBanner";
import { WarningToast } from "@/components/common/WarningToast";
import { DashboardActivityChart, type ActivitySeries } from "@/components/app/DashboardActivityChart";
import { StatCardSkeleton, TransactionRowSkeleton } from "@/components/common/Skeleton";
import { Reveal } from "@/components/motion/Reveal";
import { QuickAction } from "@/components/app/QuickAction";
import { StatCard } from "@/components/app/StatCard";
import { TransactionRow } from "@/components/app/TransactionRow";
import { recipientEditHref } from "@/constants/routes";
import { useAuth } from "@/hooks/useAuth";
import { useBeneficiaries } from "@/hooks/queries/useBeneficiaries";
import { useTransactions } from "@/hooks/queries/useTransactions";
import { useNotifications } from "@/hooks/useNotifications";
import { useTranslation } from "@/hooks/useTranslation";
import { avatarTint, formatCurrency } from "@/lib/utils";
import { mapTransactionStatus } from "@/lib/transactionStatus";
import type { ApiTransaction } from "@/api/transaction.api";

const TWO_FA_DISMISS_KEY = "xremit_2fa_nudge_dismissed";
const CHART_MONTHS = 6;

/** Buckets the user's own transactions into the last 6 months × 3 transfer methods. */
function buildActivityData(
  transactions: ApiTransaction[],
  methodLabels: { bank: string; cash: string; mobile: string },
): { categories: string[]; series: ActivitySeries[] } {
  const now = new Date();
  const buckets = Array.from({ length: CHART_MONTHS }, (_, i) => {
    const d = new Date(now.getFullYear(), now.getMonth() - (CHART_MONTHS - 1 - i), 1);
    return { year: d.getFullYear(), month: d.getMonth(), label: d.toLocaleDateString(undefined, { month: "short" }) };
  });

  const methods = [
    { match: "bank transfer", key: "bank", label: methodLabels.bank, color: "#60a5fa" },
    { match: "cash pickup", key: "cash", label: methodLabels.cash, color: "#34d399" },
    { match: "mobile money", key: "mobile", label: methodLabels.mobile, color: "#fbbf24" },
  ];

  const sums = methods.map(() => buckets.map(() => 0));

  transactions.forEach((tx) => {
    if (tx.status === 3 || tx.status === 4 || !tx.created_at) return;
    const d = new Date(tx.created_at);
    const bucketIdx = buckets.findIndex((b) => b.year === d.getFullYear() && b.month === d.getMonth());
    if (bucketIdx === -1) return;
    const methodIdx = methods.findIndex((m) => m.match === tx.remittance_data.type.toLowerCase());
    if (methodIdx === -1) return;
    sums[methodIdx][bucketIdx] += parseFloat(tx.remittance_data.send_money) || 0;
  });

  return {
    categories: buckets.map((b) => b.label),
    series: methods.map((m, i) => ({ key: m.key, label: m.label, color: m.color, values: sums[i] })),
  };
}

export default function DashboardPage() {
  const { t } = useTranslation();
  const { user } = useAuth();
  // Defaults to dismissed so a stale nudge never flashes before sessionStorage is read.
  const [twoFaDismissed, setTwoFaDismissed] = useState(true);

  useEffect(() => {
    try {
      setTwoFaDismissed(sessionStorage.getItem(TWO_FA_DISMISS_KEY) === "1");
    } catch {
      setTwoFaDismissed(false);
    }
  }, []);

  function dismissTwoFaNudge() {
    try {
      sessionStorage.setItem(TWO_FA_DISMISS_KEY, "1");
    } catch {
      /* ignore */
    }
    setTwoFaDismissed(true);
  }
  const { data: beneficiariesData, isLoading: beneficiariesLoading } = useBeneficiaries();
  const beneficiaries = beneficiariesData?.beneficiaries ?? [];
  const { data: txData, isLoading: txLoading } = useTransactions();
  const transactions = txData?.transaction ?? [];
  const { unreadCount, isLoading: notificationsLoading } = useNotifications();
  const transactionsReady = !txLoading;
  const dataReady = !beneficiariesLoading && transactionsReady && !notificationsLoading;

  // Single O(n) pass: lifetime total, pending count, and this-month vs last-month totals.
  const nowDate = new Date();
  const startOfThisMonth = new Date(nowDate.getFullYear(), nowDate.getMonth(), 1);
  const startOfLastMonth = new Date(nowDate.getFullYear(), nowDate.getMonth() - 1, 1);

  let totalSent = 0;
  let pendingCount = 0;
  let thisMonthTotal = 0;
  let lastMonthTotal = 0;
  transactions.forEach((tx) => {
    if (mapTransactionStatus(tx.status) === "pending") pendingCount += 1;
    // status 3 = failed, 4 = cancelled — exclude those from totals
    if (tx.status === 3 || tx.status === 4) return;
    const amount = parseFloat(tx.remittance_data.send_money) || 0;
    totalSent += amount;
    if (!tx.created_at) return;
    const createdAt = new Date(tx.created_at);
    if (createdAt >= startOfThisMonth) thisMonthTotal += amount;
    else if (createdAt >= startOfLastMonth) lastMonthTotal += amount;
  });

  const monthChangePct = lastMonthTotal > 0
    ? Math.round(((thisMonthTotal - lastMonthTotal) / lastMonthTotal) * 100)
    : thisMonthTotal > 0 ? 100 : 0;
  const monthTrendDirection: "up" | "down" | "flat" =
    monthChangePct > 0 ? "up" : monthChangePct < 0 ? "down" : "flat";

  const recent = transactions.slice(0, 5);

  // Build name→tx-order map (earlier index = more recent). O(n).
  const txNameOrder = new Map<string, number>();
  transactions.forEach((tx, idx) => {
    const rd = tx.remittance_data;
    const key = [rd.first_name, rd.middle_name, rd.last_name]
      .filter(Boolean).join(" ").toLowerCase();
    if (!txNameOrder.has(key)) txNameOrder.set(key, idx);
  });

  // Sort: beneficiaries with recent transactions first (by tx recency), rest after.
  const quickRecipients = [...beneficiaries]
    .sort((a, b) => {
      const keyA = [a.first_name, a.middle_name, a.last_name].filter(Boolean).join(" ").toLowerCase();
      const keyB = [b.first_name, b.middle_name, b.last_name].filter(Boolean).join(" ").toLowerCase();
      return (txNameOrder.get(keyA) ?? Infinity) - (txNameOrder.get(keyB) ?? Infinity);
    })
    .slice(0, 6);
  const firstName = user?.firstName || user?.email.split("@")[0] || "there";

  const twoFaEnabled = Boolean(user?.twoFactorEnabled);

  const hour = new Date().getHours();
  const greetingKey =
    hour < 12 ? "app.dashboard.greetingMorning"
    : hour < 18 ? "app.dashboard.greetingAfternoon"
    : "app.dashboard.greetingEvening";

  const showKycBanner = Boolean(user) && user?.kycStatus !== "verified";
  const showTwoFaNudge = Boolean(user) && !twoFaEnabled && !twoFaDismissed;

  const { categories: activityCategories, series: activitySeries } = buildActivityData(transactions, {
    bank: t("calculator.bankTransfer"),
    cash: t("calculator.cashPickup"),
    mobile: t("calculator.mobileMoney"),
  });

  return (
    <Container className="max-w-full space-y-8">
      {/* Page header — greeting + primary CTA, outside the balance card so the
          card itself stays focused on the balance. */}
      <header className="flex items-start justify-between gap-3">
        <div>
          <h1 className="text-xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-2xl">
            {t(greetingKey).replace("{name}", firstName)}
          </h1>
          <p className="mt-1 text-sm text-slate-500 dark:text-slate-400">
            {t("app.dashboard.overviewSubtitle")}
          </p>
        </div>
        <ButtonLink href="/send" size="md" className="shrink-0">
          <Send className="icon-md rtl:-scale-x-100" />
          {t("app.dashboard.quickActionSend")}
        </ButtonLink>
      </header>

      {/* Account alerts — only mounted when there's something to show, so a
          dismissed/verified state never leaves a phantom node eating the
          space-y-8 gap above the balance card. */}
      {showTwoFaNudge && (
        <Reveal>
          <WarningToast
            title={t("app.dashboard.twoFa.title")}
            message={t("app.dashboard.twoFa.message")}
            ctaLabel={t("app.dashboard.twoFa.cta")}
            ctaHref="/settings?tab=twofa"
            dismissLabel={t("app.dashboard.twoFa.dismiss")}
            onClose={dismissTwoFaNudge}
          />
        </Reveal>
      )}
      {showKycBanner && (
        <Reveal>
          <KycStatusBanner />
        </Reveal>
      )}

      {/* Stats — glanceable numbers first, before any deeper visual/list content */}
      <Reveal delay={0.05}>
        <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          {dataReady ? (
            <>
              <StatCard
                icon={TrendingUp}
                label={t("app.dashboard.thisMonthLabel")}
                value={formatCurrency(thisMonthTotal, "USD")}
                trend={{ value: `${monthChangePct > 0 ? "+" : ""}${monthChangePct}%`, direction: monthTrendDirection }}
                accent="accent"
              />
              <StatCard
                icon={Clock}
                label={t("app.dashboard.pendingTransfersLabel")}
                value={String(pendingCount)}
                accent="amber"
              />
              <StatCard
                icon={Wallet}
                label={t("app.dashboard.stat1Label")}
                value={formatCurrency(totalSent, "USD")}
              />
              <StatCard
                icon={Receipt}
                label={t("app.dashboard.stat2Label")}
                value={String(transactions.length)}
                accent="accent"
              />
              <StatCard
                icon={Users}
                label={t("app.dashboard.stat3Label")}
                value={String(beneficiaries.length)}
                accent="amber"
              />
              <StatCard
                icon={Bell}
                label={t("app.dashboard.stat4Label")}
                value={String(unreadCount)}
                accent={unreadCount > 0 ? "amber" : "slate"}
              />
            </>
          ) : (
            <>
              <StatCardSkeleton />
              <StatCardSkeleton />
              <StatCardSkeleton />
              <StatCardSkeleton />
              <StatCardSkeleton />
              <StatCardSkeleton />
            </>
          )}
        </section>
      </Reveal>

      {/* Quick actions — shortcuts right after the numbers, before the deeper chart/list content */}
      <Reveal delay={0.1}>
        <div>
          <h2 className="mb-3 flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-slate-500 dark:text-slate-400">
            <Pin className="icon-sm" />
            {t("app.dashboard.quickActionsTitle")}
          </h2>
          <div className="flex flex-wrap gap-2.5">
            <QuickAction href="/transactions" icon={History} label={t("app.dashboard.quickActionHistory")} />
            <QuickAction href="/recipients/new" icon={Users} label={t("app.dashboard.quickActionAddRecipient")} />
            <QuickAction href="/coupons" icon={Tag} label={t("app.nav.coupons")} />
          </div>
        </div>
      </Reveal>

      {/* Activity overview — full width */}
      <Reveal delay={0.15}>
        <Card className="overflow-hidden border border-slate-200/80 dark:border-slate-700/50">
          <div aria-hidden className="absolute inset-0 -z-10">
            <Image
              src="/dashboard-topo-bg.webp"
              alt=""
              fill
              priority
              sizes="100vw"
              className="object-cover object-center opacity-20 invert dark:opacity-40 dark:invert-0"
            />
            <div className="absolute inset-0 bg-gradient-to-br from-white via-slate-50 to-slate-100/80 dark:from-slate-800/95 dark:via-slate-800/85 dark:to-slate-900/90" />
          </div>

          <CardContent className="relative z-10 flex h-full flex-col">
            <h3 className="shrink-0 text-[length:var(--text-lg-fixed)] font-bold text-slate-900 dark:text-white">
              {t("agent.dashboard.activityOverview")}
            </h3>
            <div className="mt-4 min-h-0 flex-1">
              <DashboardActivityChart categories={activityCategories} series={activitySeries} />
            </div>
          </CardContent>
        </Card>
      </Reveal>

      {/* Recent activity + quick send */}
      <Reveal delay={0.2}>
        <div className="grid gap-6 xl:grid-cols-[1.6fr_1fr]">
          <Card className="flex flex-col">
            <CardContent className="flex flex-1 flex-col">
              <header className="flex items-center justify-between">
                <h2 className="text-[length:var(--text-lg-fixed)] font-bold text-slate-900 dark:text-white">
                  {t("app.dashboard.recentTitle")}
                </h2>
                <Link
                  href="/transactions"
                  className="inline-flex h-8 items-center gap-1 rounded-full border border-slate-200 px-3 text-xs font-semibold text-brand-600 transition hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700 dark:border-slate-700 dark:text-brand-400 dark:hover:border-brand-400/40 dark:hover:bg-brand-500/10"
                >
                  {t("app.dashboard.recentSeeAll")}
                  <ArrowUpRight className="h-3.5 w-3.5 rtl:-scale-x-100" />
                </Link>
              </header>
              <div className="mt-3 flex flex-1 flex-col -mx-2 space-y-0.5">
                {!transactionsReady ? (
                  <>
                    <TransactionRowSkeleton />
                    <TransactionRowSkeleton />
                    <TransactionRowSkeleton />
                  </>
                ) : recent.length === 0 ? (
                  <EmptyState icon={Receipt} title={t("app.dashboard.recentEmpty")} className="flex-1 justify-center rounded-2xl border-none bg-transparent py-10 dark:bg-transparent" />
                ) : (
                  recent.map((tr) => <TransactionRow key={tr.trx_id} transaction={tr} />)
                )}
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardContent>
              <header className="flex items-center justify-between">
                <h2 className="text-[length:var(--text-lg-fixed)] font-bold text-slate-900 dark:text-white">
                  {t("app.dashboard.quickRecipientsTitle")}
                </h2>
                <Link
                  href="/recipients"
                  className="inline-flex h-8 items-center gap-1 rounded-full border border-slate-200 px-3 text-xs font-semibold text-brand-600 transition hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700 dark:border-slate-700 dark:text-brand-400 dark:hover:border-brand-400/40 dark:hover:bg-brand-500/10"
                >
                  {t("app.dashboard.recentSeeAll")}
                  <ArrowUpRight className="h-3.5 w-3.5 rtl:-scale-x-100" />
                </Link>
              </header>
              {quickRecipients.length === 0 ? (
                <EmptyState icon={Users} title={t("app.dashboard.quickRecipientsEmpty")} className="mt-3 rounded-2xl border-none bg-transparent py-10 dark:bg-transparent" />
              ) : (
                <ul className="mt-3 space-y-1">
                  {quickRecipients.map((b) => {
                    const name = [b.first_name, b.middle_name, b.last_name].filter(Boolean).join(" ");
                    const initials = name.split(" ").map((p) => p.charAt(0)).slice(0, 2).join("");
                    return (
                      <li
                        key={b.id}
                        className="group flex origin-top items-center gap-1 rounded-2xl pe-1.5 transition-[transform,background-color] duration-200 ease-snappy hover:scale-[1.02] hover:bg-slate-50 dark:hover:bg-slate-800/60"
                      >
                        <Link
                          href={recipientEditHref(b.id)}
                          prefetch={false}
                          className="flex min-w-0 flex-1 items-center gap-3 px-2 py-2"
                        >
                          <span className={`icon-box-sm grid shrink-0 place-items-center rounded-full text-xs font-bold ${avatarTint(name)}`}>
                            {initials}
                          </span>
                          <span className="truncate text-sm font-semibold text-slate-900 dark:text-white">
                            {name}
                          </span>
                        </Link>
                        <Link
                          href={`/send?bid=${b.id}`}
                          aria-label={`${t("app.dashboard.quickActionSend")} ${name}`}
                          className="btn-icon shrink-0 text-slate-400 transition-colors group-hover:text-brand-600 dark:group-hover:text-brand-400"
                        >
                          <Send className="icon-md rtl:-scale-x-100 transition-transform duration-200 ease-snappy group-hover:-translate-y-0.5 group-hover:translate-x-0.5 motion-reduce:transition-none motion-reduce:transform-none" />
                        </Link>
                      </li>
                    );
                  })}
                </ul>
              )}
            </CardContent>
          </Card>
        </div>
      </Reveal>
    </Container>
  );
}
