"use client";

import { useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { CreditCard, Lock } from "lucide-react";
import { useMutation } from "@tanstack/react-query";
import { Container } from "@/components/common/Container";
import { Card, CardContent } from "@/components/common/Card";
import { Button } from "@/components/common/Button";
import { FormField } from "@/components/app/FormField";
import { TransferSuccessModal } from "@/components/app/TransferSuccessModal";
import { sendRemittanceApi } from "@/api/sendRemittance.api";
import { isApiError } from "@/lib/apiError";
import { useTranslation } from "@/hooks/useTranslation";
import { useKycGate } from "@/hooks/useKycGate";
import { KycGate } from "@/components/app/KycGate";
import { cn } from "@/lib/utils";

interface SuccessData {
  trxId: string;
  shareLink: string;
  downloadLink: string;
}

function formatCardNumber(raw: string): string {
  const digits = raw.replace(/\D/g, "").slice(0, 16);
  return digits.replace(/(.{4})/g, "$1 ").trim();
}

function twoDigits(raw: string): string {
  return raw.replace(/\D/g, "").slice(0, 2);
}

export default function SendAuthorizeView() {
  const { t } = useTranslation();
  const kycGateStatus = useKycGate();
  const router = useRouter();
  const searchParams = useSearchParams();
  // Identifier travels via query param only — never shown as an editable field,
  // it belongs in the submit body, not something the user should touch.
  const identifier = searchParams.get("identifier") ?? "";

  const [cardNumber, setCardNumber] = useState("");
  const [expiryYear, setExpiryYear] = useState("");
  const [expiryMonth, setExpiryMonth] = useState("");
  const [cvv, setCvv] = useState("");
  const [errors, setErrors] = useState<{ cardNumber?: string; expiry?: string; cvv?: string }>({});
  const [submitError, setSubmitError] = useState("");
  // Shown as soon as the charge succeeds, right here on this page — no navigation
  // needed to display it, since the response already carries everything the modal
  // needs. The user only leaves this page once they close it (see onClose below).
  const [successData, setSuccessData] = useState<SuccessData | null>(null);

  const mutation = useMutation({
    mutationFn: () =>
      sendRemittanceApi.authorizePayment({
        identifier,
        card_number: cardNumber.replace(/\s+/g, ""),
        // Backend expects 2-digit YY/MM — e.g. "30/12" for Dec 2030.
        date: `${expiryYear}/${expiryMonth}`,
        code: cvv,
      }) as Promise<{ trx?: string; trx_id?: string; reference?: string; share_link?: string; download_link?: string }>,
    onSuccess: (data) => {
      // Backend returns these directly in the JSON body on success — same field
      // names it previously encoded into the (now-removed) redirect_url query string.
      const trxId = data?.trx ?? data?.trx_id ?? data?.reference ?? "";
      const shareLink = data?.share_link ?? "";
      const downloadLink = data?.download_link ?? "";
      if (trxId && shareLink && downloadLink) {
        setSuccessData({ trxId, shareLink, downloadLink });
      }
      // else: fields missing — nothing to show; submitError stays empty, form stays
      // put rather than claiming a success we can't actually display.
    },
    onError: (err) => {
      setSubmitError(isApiError(err) ? err.message : t("app.send.authorize.errors.submitFailed"));
    },
  });

  function onSubmit(e: { preventDefault(): void }) {
    e.preventDefault();
    const digits = cardNumber.replace(/\s+/g, "");
    const next: typeof errors = {};
    if (!/^\d{16}$/.test(digits)) next.cardNumber = t("app.send.authorize.errors.cardNumberInvalid");
    if (!/^\d{2}$/.test(expiryYear) || !/^\d{2}$/.test(expiryMonth) || Number(expiryMonth) < 1 || Number(expiryMonth) > 12) {
      next.expiry = t("app.send.authorize.errors.expiryInvalid");
    }
    if (!/^\d{3,4}$/.test(cvv)) next.cvv = t("app.send.authorize.errors.cvvInvalid");
    setErrors(next);
    if (Object.keys(next).length > 0) return;
    setSubmitError("");
    mutation.mutate();
  }

  if (kycGateStatus) {
    return <KycGate status={kycGateStatus} />;
  }

  return (
    <Container className="max-w-lg">
      <TransferSuccessModal
        open={!!successData}
        onClose={() => router.push("/transactions")}
        trxId={successData?.trxId ?? ""}
        shareLink={successData?.shareLink ?? ""}
        downloadLink={successData?.downloadLink ?? ""}
      />
      <Card>
        <CardContent>
          <div className="mx-auto mb-5 grid h-14 w-14 place-items-center rounded-2xl bg-gradient-to-br from-brand-50 to-indigo-50 text-brand-600 dark:from-brand-500/10 dark:to-indigo-500/10 dark:text-brand-300">
            <CreditCard className="h-6 w-6" />
          </div>
          <h2 className="text-center text-lg font-bold text-slate-900 dark:text-white">
            {t("app.send.authorize.title")}
          </h2>
          <p className="mt-1 text-center text-sm text-slate-500 dark:text-slate-400">
            {t("app.send.authorize.subtitle")}
          </p>

          <form onSubmit={onSubmit} noValidate className="mt-6 space-y-4">
            <FormField
              label={t("app.send.authorize.cardNumberLabel")}
              value={cardNumber}
              onChange={(e) => {
                setCardNumber(formatCardNumber(e.target.value));
                setErrors((prev) => ({ ...prev, cardNumber: undefined }));
              }}
              inputMode="numeric"
              autoComplete="off"
              placeholder={t("app.send.authorize.cardNumberPlaceholder")}
              error={errors.cardNumber}
              required
            />

            <div className="grid grid-cols-2 gap-x-4 gap-y-1.5">
              {/* Labels and inputs each share one grid row, so a wrapped label
                  (long translations, e.g. French "Code De Sécurité") pushes
                  both input groups down together instead of only its own column.
                  Columns are split 50/50 (not 2:1) and labels forced to a single
                  line so longer translations get room instead of wrapping. */}
              <label className="block whitespace-nowrap text-[length:var(--text-sm-fixed)] font-medium capitalize tracking-wide text-slate-500 dark:text-slate-400">
                {t("app.send.authorize.expiryLabel")}
                <span className="ms-1 font-bold text-rose-500 dark:text-rose-400">*</span>
              </label>
              <label className="block whitespace-nowrap text-[length:var(--text-sm)] font-medium capitalize tracking-wide text-slate-500 dark:text-slate-400">
                {t("app.send.authorize.cvvLabel")}
                <span className="ms-1 font-bold text-rose-500 dark:text-rose-400">*</span>
              </label>

              <div className="grid grid-cols-2 gap-2">
                <input
                  value={expiryYear}
                  onChange={(e) => {
                    setExpiryYear(twoDigits(e.target.value));
                    setErrors((prev) => ({ ...prev, expiry: undefined }));
                  }}
                  inputMode="numeric"
                  autoComplete="off"
                  placeholder={t("app.send.authorize.yearLabel")}
                  aria-label={t("app.send.authorize.yearLabel")}
                  aria-invalid={errors.expiry ? true : undefined}
                  className="h-11 w-full rounded-2xl border border-slate-200 bg-white px-4 text-center text-sm text-slate-900 outline-none transition placeholder:text-slate-400 focus:border-brand-500 focus:shadow-glow-sm dark:border-slate-700 dark:bg-slate-900 dark:text-white"
                />
                <input
                  value={expiryMonth}
                  onChange={(e) => {
                    setExpiryMonth(twoDigits(e.target.value));
                    setErrors((prev) => ({ ...prev, expiry: undefined }));
                  }}
                  inputMode="numeric"
                  autoComplete="off"
                  placeholder={t("app.send.authorize.monthLabel")}
                  aria-label={t("app.send.authorize.monthLabel")}
                  aria-invalid={errors.expiry ? true : undefined}
                  className="h-11 w-full rounded-2xl border border-slate-200 bg-white px-4 text-center text-sm text-slate-900 outline-none transition placeholder:text-slate-400 focus:border-brand-500 focus:shadow-glow-sm dark:border-slate-700 dark:bg-slate-900 dark:text-white"
                />
              </div>
              <input
                value={cvv}
                onChange={(e) => {
                  setCvv(e.target.value.replace(/\D/g, "").slice(0, 4));
                  setErrors((prev) => ({ ...prev, cvv: undefined }));
                }}
                type="password"
                inputMode="numeric"
                autoComplete="off"
                placeholder="123"
                aria-label={t("app.send.authorize.cvvLabel")}
                aria-invalid={errors.cvv ? true : undefined}
                className={cn(
                  "h-11 w-full rounded-2xl border bg-white px-4 text-sm text-slate-900 outline-none transition placeholder:text-slate-400 focus:border-brand-500 focus:shadow-glow-sm dark:bg-slate-900 dark:text-white",
                  errors.cvv ? "border-rose-300 dark:border-rose-400/40" : "border-slate-200 dark:border-slate-700",
                )}
              />

              {errors.expiry && (
                <p className="text-xs font-medium text-rose-600 dark:text-rose-400">{errors.expiry}</p>
              )}
              {errors.cvv && (
                <p className="text-xs font-medium text-rose-600 dark:text-rose-400">{errors.cvv}</p>
              )}
            </div>

            {submitError && (
              <p className="text-xs font-medium text-rose-600 dark:text-rose-400">{submitError}</p>
            )}

            <Button
              type="submit"
              size="lg"
              loading={mutation.isPending}
              disabled={mutation.isPending}
              className="w-full"
            >
              {mutation.isPending ? t("app.send.authorize.submitting") : t("app.send.authorize.submit")}
            </Button>

            <div className="flex items-center justify-center gap-1.5 text-xs text-slate-500 dark:text-slate-400">
              <Lock className="h-3 w-3" aria-hidden />
              <span>{t("app.send.authorize.securityNote")}</span>
            </div>
          </form>
        </CardContent>
      </Card>
    </Container>
  );
}
