import type { Metadata } from "next";
import { Clock, Coins, TrendingUp, Wallet, type LucideIcon } from "lucide-react";
import { PageHeader } from "@/components/shared/page-header";
import { EmptyState } from "@/components/shared/empty-state";
import { AddFundsForm } from "@/components/panel/funds/add-funds-form";
import { PaymentHistory } from "@/components/panel/funds/payment-history";
import type { PaymentHistoryRow, PaymentMethodDTO } from "@/components/panel/funds/types";
import { db } from "@/lib/db";
import { requireUser } from "@/lib/guards";
import { dec, iso, money, signedMoney } from "@/lib/serialize";
import { fundsTexts } from "@/lib/i18n/funds";
import {
  allowedMethodKeys,
  integrationFor,
  isMethodAllowed,
  isNewUser,
} from "@/lib/validation/payments";

export const metadata: Metadata = { title: "Add funds" };

const HISTORY_LIMIT = 40;

function shortId(id: string): string {
  if (id.length <= 12) return id;
  return `${id.slice(0, 6)}…${id.slice(-4)}`;
}

function Stat({
  icon: Icon,
  label,
  value,
  tone = "primary",
}: {
  icon: LucideIcon;
  label: string;
  value: string;
  tone?: "primary" | "cyan" | "amber" | "muted";
}) {
  const tones: Record<string, string> = {
    primary: "bg-primary/10 text-primary",
    cyan: "bg-cyan-500/10 text-cyan-600 dark:text-cyan-400",
    amber: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
    muted: "bg-muted text-muted-foreground",
  };
  return (
    <div className="rounded-2xl border bg-card p-4 shadow-sm">
      <div className="flex items-center gap-3">
        <span
          className={`flex size-9 shrink-0 items-center justify-center rounded-xl ${tones[tone]}`}
        >
          <Icon className="size-[18px]" />
        </span>
        <div className="min-w-0">
          <p className="truncate text-xs text-muted-foreground">{label}</p>
          <p className="font-mono text-lg font-semibold tabular-nums">{value}</p>
        </div>
      </div>
    </div>
  );
}

export default async function AddFundsPage(props: {
  searchParams: Promise<Record<string, string | string[] | undefined>>;
}) {
  const session = await requireUser();
  const searchParams = await props.searchParams;
  const requestedMethod =
    typeof searchParams.method === "string" ? searchParams.method : undefined;

  const [user, allMethods, payments, ledger, completedSum, pendingSum] = await Promise.all([
    db.user.findUnique({
      where: { id: session.id },
      select: {
        balance: true,
        spent: true,
        createdAt: true,
        allowedPaymentMethods: true,
      },
    }),
    db.paymentMethod.findMany({ orderBy: [{ position: "asc" }, { name: "asc" }] }),
    db.payment.findMany({
      where: { userId: session.id },
      orderBy: { createdAt: "desc" },
      take: HISTORY_LIMIT,
      select: {
        id: true,
        method: true,
        amount: true,
        fee: true,
        status: true,
        memo: true,
        fraudRisk: true,
        createdAt: true,
      },
    }),
    db.transaction.findMany({
      where: { userId: session.id, type: { in: ["FEE", "BONUS"] } },
      orderBy: { createdAt: "desc" },
      take: HISTORY_LIMIT,
      select: {
        id: true,
        type: true,
        amount: true,
        method: true,
        note: true,
        createdAt: true,
      },
    }),
    db.payment.aggregate({
      where: { userId: session.id, status: "COMPLETED" },
      _sum: { amount: true },
    }),
    db.payment.aggregate({
      where: { userId: session.id, status: "PENDING" },
      _sum: { amount: true },
    }),
  ]);

  const nameByKey = new Map<string, string>(
    allMethods.map((m) => [m.key, m.name] as [string, string]),
  );

  const eligibility = {
    isNew: user ? isNewUser(user.createdAt) : false,
    allowed: allowedMethodKeys(user?.allowedPaymentMethods),
  };

  const methods: PaymentMethodDTO[] = allMethods
    .filter((m) => isMethodAllowed(m, eligibility))
    .map((m) => ({
      key: m.key,
      name: m.name,
      instructionsHtml: m.instructionsHtml,
      min: m.min ? dec(m.min) : null,
      max: m.max ? dec(m.max) : null,
      minLabel: m.min ? money(m.min) : null,
      maxLabel: m.max ? money(m.max) : null,
      bonusPercent: dec(m.bonusPercent),
      bonusFrom: dec(m.bonusFrom),
      bonusFromLabel: money(m.bonusFrom),
      integration: integrationFor(m.key),
    }));

  const rows: PaymentHistoryRow[] = [
    ...payments.map<PaymentHistoryRow>((p) => ({
      id: p.id,
      shortId: shortId(p.id),
      kind: "PAYMENT",
      createdAt: iso(p.createdAt),
      method: nameByKey.get(p.method) ?? p.method,
      amount: money(p.amount),
      positive: p.status === "COMPLETED",
      status: p.status,
      note: p.memo,
      fraudRisk: p.fraudRisk,
    })),
    ...ledger.map<PaymentHistoryRow>((t) => ({
      id: t.id,
      shortId: shortId(t.id),
      kind: t.type === "BONUS" ? "BONUS" : "FEE",
      createdAt: iso(t.createdAt),
      method: t.method ? (nameByKey.get(t.method) ?? t.method) : fundsTexts.ledgerNote,
      amount: signedMoney(t.amount),
      positive: !String(t.amount).startsWith("-"),
      status: "COMPLETED",
      note: t.note,
      fraudRisk: null,
    })),
  ]
    .sort((a, b) => (a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0))
    .slice(0, HISTORY_LIMIT);

  return (
    <div className="mx-auto w-full max-w-screen-2xl p-4 sm:p-6">
      <PageHeader
        title={fundsTexts.title}
        description={fundsTexts.subtitle}
        icon={Wallet}
      />

      <div className="mb-6 grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
        <Stat
          icon={Wallet}
          label={fundsTexts.currentBalance}
          value={money(user?.balance ?? 0)}
          tone="primary"
        />
        <Stat
          icon={TrendingUp}
          label={fundsTexts.totalDeposited}
          value={money(completedSum._sum.amount ?? 0)}
          tone="cyan"
        />
        <Stat
          icon={Clock}
          label={fundsTexts.pendingDeposits}
          value={money(pendingSum._sum.amount ?? 0)}
          tone="amber"
        />
        <Stat
          icon={Coins}
          label={fundsTexts.lifetimeSpent}
          value={money(user?.spent ?? 0)}
          tone="muted"
        />
      </div>

      <div className="grid gap-6 lg:grid-cols-3">
        <div className="rounded-2xl border bg-card p-5 shadow-sm sm:p-6 lg:col-span-2">
          {methods.length ? (
            <AddFundsForm methods={methods} initialMethod={requestedMethod} />
          ) : (
            <EmptyState
              icon={Wallet}
              title={fundsTexts.noMethods}
              hint={fundsTexts.noMethodsHint}
              className="border-none"
            />
          )}
        </div>

        <aside className="space-y-4">
          <div className="rounded-2xl border bg-card p-5 shadow-sm">
            <h2 className="font-display text-sm font-semibold">How a deposit works</h2>
            <ol className="mt-3 space-y-3 text-sm text-muted-foreground">
              {[
                "Pick a method and read its instructions.",
                "Send the money exactly as described, with your username as reference.",
                "Submit the form — the payment is recorded as pending.",
                "An administrator confirms it and your balance is credited instantly.",
              ].map((step, index) => (
                <li key={step} className="flex gap-3">
                  <span className="flex size-5 shrink-0 items-center justify-center rounded-full bg-primary/10 font-mono text-[11px] font-semibold text-primary">
                    {index + 1}
                  </span>
                  <span className="leading-relaxed">{step}</span>
                </li>
              ))}
            </ol>
          </div>

          <div className="rounded-2xl border bg-card p-5 shadow-sm">
            <h2 className="font-display text-sm font-semibold">Good to know</h2>
            <ul className="mt-3 space-y-2 text-sm text-muted-foreground">
              <li>Deposits are never reversed once your balance is credited.</li>
              <li>Bonuses are added as a separate line in your history.</li>
              <li>
                Payments stuck as pending for more than a few hours? Open a ticket with the
                payment ID.
              </li>
            </ul>
          </div>
        </aside>
      </div>

      <div className="mt-6 rounded-2xl border bg-card shadow-sm">
        <div className="flex flex-col gap-1 border-b p-5 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <h2 className="font-display text-base font-semibold">{fundsTexts.historyTitle}</h2>
            <p className="text-sm text-muted-foreground">{fundsTexts.historyHint}</p>
          </div>
        </div>
        <div className="p-2 sm:p-4">
          <PaymentHistory rows={rows} />
        </div>
      </div>
    </div>
  );
}
