"use client";

import * as React from "react";
import { useActionState } from "react";
import { useRouter } from "next/navigation";
import { Decimal } from "decimal.js";
import { toast } from "sonner";
import { Check, Loader2, Plus, Search, UserRound } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { money } from "@/lib/serialize";
import { cn } from "@/lib/utils";
import { bonusAmount, parseAmount } from "@/lib/validation/payments";
import { adminTexts } from "@/lib/i18n/admin";
import { adminPaymentsTexts as t } from "@/lib/i18n/admin-payments";
import {
  addPaymentAction,
  searchPaymentUsersAction,
} from "@/lib/actions/admin-payments";

export type AddPaymentMethod = {
  key: string;
  name: string;
  active: boolean;
  bonusPercent: string;
  bonusFrom: string;
};

type UserOption = {
  id: string;
  username: string;
  email: string;
  balance: string;
  status: string;
};

type State =
  | { ok: true; data?: { paymentId: string; message: string } }
  | { ok: false; error: string; fieldErrors?: Record<string, string> }
  | null;

function FieldError({ message }: { message?: string }) {
  if (!message) return null;
  return <p className="text-[11px] text-rose-600 dark:text-rose-400">{message}</p>;
}

export function AddPaymentDialog({ methods }: { methods: AddPaymentMethod[] }) {
  const router = useRouter();
  const [open, setOpen] = React.useState(false);
  const [term, setTerm] = React.useState("");
  const [results, setResults] = React.useState<UserOption[]>([]);
  const [searching, setSearching] = React.useState(false);
  const [selected, setSelected] = React.useState<UserOption | null>(null);
  const [methodKey, setMethodKey] = React.useState(methods[0]?.key ?? "");
  const [amount, setAmount] = React.useState("");
  const [fee, setFee] = React.useState("");
  const [applyBonus, setApplyBonus] = React.useState(true);

  const [state, formAction, pending] = useActionState<State, FormData>(
    addPaymentAction,
    null,
  );

  React.useEffect(() => {
    const q = term.trim();
    if (selected || q.length < 2) {
      setResults([]);
      setSearching(false);
      return;
    }
    let cancelled = false;
    setSearching(true);
    const timer = setTimeout(() => {
      searchPaymentUsersAction(q)
        .then((found) => {
          if (!cancelled) setResults(found);
        })
        .catch(() => {
          if (!cancelled) setResults([]);
        })
        .finally(() => {
          if (!cancelled) setSearching(false);
        });
    }, 250);
    return () => {
      cancelled = true;
      clearTimeout(timer);
    };
  }, [term, selected]);

  React.useEffect(() => {
    if (!state) return;
    if (state.ok) {
      toast.success(state.data?.message ?? t.confirmedToast);
      setOpen(false);
      setSelected(null);
      setTerm("");
      setAmount("");
      setFee("");
      router.refresh();
    } else {
      toast.error(state.error);
    }
  }, [state, router]);

  const method = methods.find((m) => m.key === methodKey) ?? methods[0];
  const fieldErrors = state && !state.ok ? (state.fieldErrors ?? {}) : {};

  const amountDec = parseAmount(amount) ?? new Decimal(0);
  const feeDec = parseAmount(fee) ?? new Decimal(0);
  const bonusDec =
    method && applyBonus
      ? bonusAmount(amountDec, method.bonusPercent, method.bonusFrom)
      : new Decimal(0);
  const netDec = amountDec.minus(feeDec).plus(bonusDec);
  const hasBonusRule = method ? new Decimal(method.bonusPercent || "0").greaterThan(0) : false;

  return (
    <>
      <Button type="button" size="sm" onClick={() => setOpen(true)}>
        <Plus className="size-3.5" />
        {t.addPayment}
      </Button>

      <Dialog
        open={open}
        onOpenChange={(next) => {
          setOpen(next);
          if (!next) {
            setTerm("");
            setResults([]);
          }
        }}
      >
        <DialogContent className="sm:max-w-lg">
          <form action={formAction} className="space-y-4">
            <DialogHeader>
              <DialogTitle className="text-base">{t.addPaymentTitle}</DialogTitle>
              <DialogDescription className="text-sm">
                {t.addPaymentHint}
              </DialogDescription>
            </DialogHeader>

            <input type="hidden" name="userId" value={selected?.id ?? ""} />
            <input type="hidden" name="applyBonus" value={applyBonus ? "1" : "0"} />

            <div className="space-y-1.5">
              <Label className="text-xs font-medium">{t.fieldUser}</Label>

              {selected ? (
                <div className="flex items-center gap-2 rounded-lg border bg-muted/40 px-2.5 py-1.5">
                  <UserRound className="size-4 shrink-0 text-muted-foreground" />
                  <div className="min-w-0 leading-tight">
                    <div className="truncate text-sm font-medium">
                      {selected.username}
                    </div>
                    <div className="truncate text-xs text-muted-foreground">
                      {selected.email} · {selected.balance}
                    </div>
                  </div>
                  <Button
                    type="button"
                    size="sm"
                    variant="ghost"
                    className="ml-auto shrink-0"
                    onClick={() => {
                      setSelected(null);
                      setTerm("");
                    }}
                  >
                    {t.fieldUserChange}
                  </Button>
                </div>
              ) : (
                <>
                  <div className="relative">
                    <Search className="pointer-events-none absolute top-1/2 left-2 size-3.5 -translate-y-1/2 text-muted-foreground" />
                    <Input
                      value={term}
                      onChange={(e) => setTerm(e.target.value)}
                      placeholder={t.fieldUserSearch}
                      aria-label={t.fieldUserSearch}
                      autoComplete="off"
                      className="h-8 pl-7 text-sm"
                    />
                    {searching ? (
                      <Loader2 className="absolute top-1/2 right-2 size-3.5 -translate-y-1/2 animate-spin text-muted-foreground" />
                    ) : null}
                  </div>

                  {term.trim().length >= 2 ? (
                    <div className="max-h-48 overflow-y-auto rounded-lg border">
                      {results.length === 0 ? (
                        <p className="px-2.5 py-3 text-xs text-muted-foreground">
                          {searching ? t.fieldUserSearching : t.fieldUserNoResults}
                        </p>
                      ) : (
                        <ul>
                          {results.map((user) => (
                            <li key={user.id}>
                              <button
                                type="button"
                                onClick={() => setSelected(user)}
                                className="flex w-full items-center gap-2 border-b px-2.5 py-1.5 text-left transition-colors last:border-0 hover:bg-muted/60"
                              >
                                <div className="min-w-0 leading-tight">
                                  <div className="truncate text-sm font-medium">
                                    {user.username}
                                  </div>
                                  <div className="truncate text-xs text-muted-foreground">
                                    {user.email}
                                  </div>
                                </div>
                                <span className="ml-auto shrink-0 font-mono text-xs tabular-nums text-muted-foreground">
                                  {user.balance}
                                </span>
                              </button>
                            </li>
                          ))}
                        </ul>
                      )}
                    </div>
                  ) : (
                    <p className="text-[11px] text-muted-foreground">{t.fieldUserHint}</p>
                  )}
                </>
              )}
              <FieldError message={fieldErrors.userId} />
            </div>

            <div className="space-y-1.5">
              <Label htmlFor="admin-payment-method" className="text-xs font-medium">
                {t.fieldMethod}
              </Label>
              <NativeSelect
                id="admin-payment-method"
                name="method"
                value={methodKey}
                onChange={(e) => setMethodKey(e.target.value)}
                className="w-full"
              >
                {methods.map((m) => (
                  <NativeSelectOption key={m.key} value={m.key}>
                    {m.active ? m.name : `${m.name} (inactive)`}
                  </NativeSelectOption>
                ))}
              </NativeSelect>
              <FieldError message={fieldErrors.method} />
            </div>

            <div className="grid gap-3 sm:grid-cols-2">
              <div className="space-y-1.5">
                <Label htmlFor="admin-payment-amount" className="text-xs font-medium">
                  {t.fieldAmount}
                </Label>
                <Input
                  id="admin-payment-amount"
                  name="amount"
                  value={amount}
                  onChange={(e) => setAmount(e.target.value)}
                  inputMode="decimal"
                  placeholder="0.00"
                  required
                  className="h-8 font-mono text-sm tabular-nums"
                />
                <FieldError message={fieldErrors.amount} />
              </div>

              <div className="space-y-1.5">
                <Label htmlFor="admin-payment-fee" className="text-xs font-medium">
                  {t.fieldFee}
                </Label>
                <Input
                  id="admin-payment-fee"
                  name="fee"
                  value={fee}
                  onChange={(e) => setFee(e.target.value)}
                  inputMode="decimal"
                  placeholder="0.00"
                  className="h-8 font-mono text-sm tabular-nums"
                />
                <p className="text-[11px] text-muted-foreground">{t.fieldFeeHint}</p>
                <FieldError message={fieldErrors.fee} />
              </div>
            </div>

            <div className="space-y-1.5">
              <Label htmlFor="admin-payment-external" className="text-xs font-medium">
                {t.fieldExternalId}
              </Label>
              <Input
                id="admin-payment-external"
                name="externalId"
                placeholder="TX-000123"
                className="h-8 font-mono text-sm"
              />
            </div>

            <div className="space-y-1.5">
              <Label htmlFor="admin-payment-memo" className="text-xs font-medium">
                {t.fieldMemo}
              </Label>
              <Textarea
                id="admin-payment-memo"
                name="memo"
                rows={3}
                required
                placeholder={t.fieldMemoHint}
                className="text-sm"
              />
              <FieldError message={fieldErrors.memo} />
            </div>

            {hasBonusRule ? (
              <label className="flex cursor-pointer items-start gap-2 rounded-lg border bg-muted/30 px-2.5 py-2">
                <input
                  type="checkbox"
                  checked={applyBonus}
                  onChange={(e) => setApplyBonus(e.target.checked)}
                  className="mt-0.5 size-3.5 accent-blue-600"
                />
                <span className="text-xs leading-tight">
                  <span className="font-medium">{t.fieldBonus}</span>
                  <span className="block text-muted-foreground">
                    {method?.bonusPercent}% from {money(method?.bonusFrom ?? "0")}
                  </span>
                </span>
              </label>
            ) : null}

            <div
              className={cn(
                "flex flex-wrap items-center gap-x-4 gap-y-1 rounded-lg bg-muted/40 px-2.5 py-2 text-xs",
                amountDec.lessThanOrEqualTo(0) && "opacity-60",
              )}
            >
              {bonusDec.greaterThan(0) ? (
                <span className="text-cyan-600 dark:text-cyan-400">
                  {t.bonusPreview(money(bonusDec.toFixed(5)))}
                </span>
              ) : null}
              <span className="font-mono tabular-nums">
                {t.netPreview(money(netDec.toFixed(5)))}
              </span>
            </div>

            <DialogFooter>
              <Button
                type="button"
                variant="outline"
                size="lg"
                onClick={() => setOpen(false)}
              >
                {adminTexts.common.cancel}
              </Button>
              <Button type="submit" size="lg" disabled={pending || !selected}>
                {pending ? (
                  <Loader2 className="size-4 animate-spin" />
                ) : (
                  <Check className="size-4" />
                )}
                {pending ? t.submitting : t.submit}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>
    </>
  );
}

export default AddPaymentDialog;
