"use client";

import * as React from "react";
import { useActionState } from "react";
import { Decimal } from "decimal.js";
import { toast } from "sonner";
import {
  Bitcoin,
  CreditCard,
  Landmark,
  Sparkles,
  TriangleAlert,
  Wallet,
  type LucideIcon,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import { money } from "@/lib/serialize";
import { fundsTexts } from "@/lib/i18n/funds";
import { createDepositAction } from "@/lib/actions/payments";
import { bonusAmount, parseAmount, type PaymentActionState } from "@/lib/validation/payments";
import { AdminHtml } from "./admin-html";
import type { PaymentMethodDTO } from "./types";

const QUICK_AMOUNTS = [10, 25, 50, 100, 250, 500];

function iconFor(method: PaymentMethodDTO): LucideIcon {
  if (method.integration === "cryptomus") return Bitcoin;
  if (method.integration === "paypal") return Wallet;
  if (method.key.toLowerCase().includes("card")) return CreditCard;
  return Landmark;
}

function limitsLabel(method: PaymentMethodDTO): string {
  const min = method.minLabel ?? fundsTexts.noLimit;
  const max = method.maxLabel ?? fundsTexts.noLimit;
  return `${min} – ${max}`;
}

function decOf(value: string | null | undefined): Decimal {
  try {
    return new Decimal(value && value !== "" ? value : "0");
  } catch {
    return new Decimal(0);
  }
}

export function AddFundsForm({
  methods,
  initialMethod,
}: {
  methods: PaymentMethodDTO[];
  initialMethod?: string;
}) {
  const first = methods[0]?.key ?? "";
  const preselected =
    initialMethod && methods.some((m) => m.key === initialMethod) ? initialMethod : first;

  const [selected, setSelected] = React.useState(preselected);
  const [amount, setAmount] = React.useState("");
  const [state, formAction, pending] = useActionState<PaymentActionState, FormData>(
    createDepositAction,
    null,
  );

  React.useEffect(() => {
    if (!state) return;
    if (state.ok) {
      const data = state.data as { integrationPending?: boolean } | undefined;
      toast.success(
        data?.integrationPending ? fundsTexts.gatewayCreated : fundsTexts.manualCreated,
      );
      setAmount("");
    } else {
      toast.error(state.error);
    }
  }, [state]);

  const method = methods.find((m) => m.key === selected) ?? methods[0];
  if (!method) return null;

  const failure = state && state.ok === false ? state : null;
  const fieldErrors = failure?.fieldErrors ?? {};
  const success = state && state.ok === true ? state : null;
  const successData = success?.data as { integrationPending?: boolean } | undefined;

  const parsedAmount = parseAmount(amount);
  const bonus = bonusAmount(parsedAmount ?? 0, method.bonusPercent, method.bonusFrom);
  const bonusPct = decOf(method.bonusPercent);
  const bonusFrom = decOf(method.bonusFrom);
  const hasBonus = bonusPct.greaterThan(0);
  const missingForBonus =
    hasBonus && parsedAmount && parsedAmount.lessThan(bonusFrom)
      ? bonusFrom.minus(parsedAmount)
      : null;
  const credited = (parsedAmount ?? new Decimal(0)).plus(bonus);

  return (
    <form action={formAction} className="space-y-6">
      <input type="hidden" name="method" value={selected} />

      {/* ------------------------------------------------------ method */}
      <fieldset className="space-y-3" disabled={pending}>
        <div className="space-y-1">
          <Label className="text-sm font-medium">{fundsTexts.methodLabel}</Label>
          <p className="text-xs text-muted-foreground">{fundsTexts.methodHint}</p>
        </div>

        <div
          role="radiogroup"
          aria-label={fundsTexts.methodLabel}
          className="grid gap-3 sm:grid-cols-2"
        >
          {methods.map((m) => {
            const Icon = iconFor(m);
            const active = m.key === selected;
            const pct = decOf(m.bonusPercent);
            return (
              <label
                key={m.key}
                className={cn(
                  "group relative flex cursor-pointer items-start gap-3 rounded-xl border p-3.5 transition-colors",
                  active
                    ? "border-primary bg-primary/5 ring-1 ring-primary/30"
                    : "hover:border-primary/40 hover:bg-muted/40",
                  pending && "cursor-not-allowed opacity-70",
                )}
              >
                <input
                  type="radio"
                  name="method-choice"
                  value={m.key}
                  checked={active}
                  onChange={() => setSelected(m.key)}
                  disabled={pending}
                  className="sr-only"
                />
                <span
                  className={cn(
                    "mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-lg transition-colors",
                    active
                      ? "bg-primary text-primary-foreground"
                      : "bg-muted text-muted-foreground group-hover:text-foreground",
                  )}
                >
                  <Icon className="size-[18px]" />
                </span>
                <span className="min-w-0 flex-1 space-y-0.5">
                  <span className="block truncate text-sm font-medium">{m.name}</span>
                  <span className="block font-mono text-xs text-muted-foreground">
                    {limitsLabel(m)}
                  </span>
                  {pct.greaterThan(0) ? (
                    <span className="mt-1 inline-flex items-center gap-1 rounded-full bg-cyan-100 px-2 py-0.5 text-[11px] font-medium text-cyan-700 dark:bg-cyan-500/15 dark:text-cyan-400">
                      <Sparkles className="size-3" />+{pct.toFixed(0)}% bonus
                    </span>
                  ) : null}
                </span>
              </label>
            );
          })}
        </div>
        {fieldErrors.method ? (
          <p className="text-xs font-medium text-destructive">{fieldErrors.method}</p>
        ) : null}
      </fieldset>

      {/* ------------------------------------------------ instructions */}
      {method.instructionsHtml ? (
        <div className="rounded-xl border bg-muted/30 p-4">
          <p className="mb-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
            {fundsTexts.instructionsTitle}
          </p>
          <AdminHtml html={method.instructionsHtml} />
        </div>
      ) : null}

      {/* ------------------------------------------------------ amount */}
      <fieldset className="space-y-3" disabled={pending}>
        <div className="space-y-1">
          <Label htmlFor="amount" className="text-sm font-medium">
            {fundsTexts.amountLabel}
          </Label>
          <p className="text-xs text-muted-foreground">
            {fundsTexts.limits}: <span className="font-mono">{limitsLabel(method)}</span>
          </p>
        </div>

        <div className="relative">
          <span className="pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 font-mono text-base text-muted-foreground">
            $
          </span>
          <input
            id="amount"
            name="amount"
            type="text"
            inputMode="decimal"
            autoComplete="off"
            placeholder={fundsTexts.amountPlaceholder}
            value={amount}
            onChange={(e) => setAmount(e.target.value.replace(/[^\d.,]/g, ""))}
            disabled={pending}
            aria-invalid={fieldErrors.amount ? true : undefined}
            className={cn(
              "h-12 w-full rounded-lg border border-input bg-transparent pl-8 pr-3 font-mono text-lg tabular-nums outline-none transition-colors",
              "placeholder:font-sans placeholder:text-base placeholder:text-muted-foreground",
              "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
              "disabled:cursor-not-allowed disabled:opacity-50",
              fieldErrors.amount && "border-destructive ring-3 ring-destructive/20",
            )}
          />
        </div>
        {fieldErrors.amount ? (
          <p className="text-xs font-medium text-destructive">{fieldErrors.amount}</p>
        ) : null}

        <div className="flex flex-wrap gap-2">
          {QUICK_AMOUNTS.filter((value) => {
            const d = new Decimal(value);
            if (method.min && d.lessThan(method.min)) return false;
            if (method.max && d.greaterThan(method.max)) return false;
            return true;
          }).map((value) => (
            <button
              key={value}
              type="button"
              disabled={pending}
              onClick={() => setAmount(String(value))}
              className={cn(
                "rounded-lg border px-3 py-1.5 font-mono text-xs transition-colors",
                amount === String(value)
                  ? "border-primary bg-primary/10 text-primary"
                  : "text-muted-foreground hover:border-primary/40 hover:text-foreground",
              )}
            >
              ${value}
            </button>
          ))}
        </div>

        {hasBonus ? (
          <div className="flex items-start gap-2 rounded-lg bg-cyan-500/10 p-3 text-xs text-cyan-800 dark:text-cyan-300">
            <Sparkles className="mt-0.5 size-3.5 shrink-0" />
            <p>
              {bonus.greaterThan(0)
                ? fundsTexts.bonusApplied(money(bonus.toFixed(5)))
                : missingForBonus
                  ? fundsTexts.bonusMissing(money(missingForBonus.toFixed(5)), bonusPct.toFixed(0))
                  : fundsTexts.bonusHint(bonusPct.toFixed(0), method.bonusFromLabel)}
            </p>
          </div>
        ) : null}
      </fieldset>

      {/* ----------------------------------------------------- summary */}
      {parsedAmount && parsedAmount.greaterThan(0) ? (
        <dl className="space-y-1.5 rounded-xl border bg-muted/30 p-4 text-sm">
          <div className="flex items-center justify-between">
            <dt className="text-muted-foreground">{fundsTexts.youPay}</dt>
            <dd className="font-mono tabular-nums">{money(parsedAmount.toFixed(5))}</dd>
          </div>
          {bonus.greaterThan(0) ? (
            <div className="flex items-center justify-between text-cyan-700 dark:text-cyan-400">
              <dt>{fundsTexts.bonusRow}</dt>
              <dd className="font-mono tabular-nums">+{money(bonus.toFixed(5))}</dd>
            </div>
          ) : null}
          <div className="flex items-center justify-between border-t pt-1.5 font-medium">
            <dt>{fundsTexts.youGet}</dt>
            <dd className="font-mono tabular-nums">{money(credited.toFixed(5))}</dd>
          </div>
        </dl>
      ) : null}

      {/* --------------------------------------- gateway pending notice */}
      {method.integration !== "manual" ? (
        <div className="flex items-start gap-2.5 rounded-xl border border-amber-300/60 bg-amber-50 p-3.5 text-xs leading-relaxed text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200">
          <TriangleAlert className="mt-0.5 size-4 shrink-0" />
          <div className="space-y-0.5">
            <p className="font-medium">{fundsTexts.integrationPendingTitle}</p>
            <p>{fundsTexts.integrationPendingBody(method.name)}</p>
          </div>
        </div>
      ) : null}

      {failure && !fieldErrors.amount && !fieldErrors.method ? (
        <p className="rounded-lg bg-destructive/10 px-3 py-2 text-sm text-destructive">
          {failure.error}
        </p>
      ) : null}

      {success ? (
        <p className="rounded-lg bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-400">
          {successData?.integrationPending
            ? fundsTexts.gatewayCreated
            : fundsTexts.manualCreated}
        </p>
      ) : null}

      <Button
        type="submit"
        size="lg"
        disabled={pending}
        className="h-11 w-full px-6 text-sm sm:w-auto"
      >
        {pending ? fundsTexts.submitting : fundsTexts.submit}
      </Button>
    </form>
  );
}

export default AddFundsForm;
