"use client";

import { useEffect, useRef, useState } from "react";
import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import QRCode from "qrcode";
import {
  Loader2,
  Copy,
  CheckCircle2,
  Clock,
  AlertTriangle,
  ArrowLeft,
  Smartphone,
} from "lucide-react";
import { toast } from "sonner";
import { paymentApi } from "@/lib/api/client";
import { zMsg } from "@/lib/utils/translated-zod";
import { cn } from "@/lib/utils/cn";

/* ───────────────────────────── Types ───────────────────────────── */

interface Instructions {
  configured: boolean;
  enabled: boolean;
  upiId: string | null;
  payeeName: string | null;
  instructionsHi: string | null;
  instructionsEn: string | null;
  upiLink: string | null;
  amountPaise: number;
  gstPaise: number;
  totalPaise: number;
  currency: string;
  paperReferenceNo: string | null;
  paymentStatus:
    | "PENDING"
    | "AWAITING_CONFIRMATION"
    | "SUCCESS"
    | "REJECTED"
    | "CANCELLED"
    | "FAILED"
    | "REFUNDED";
  declaredReference: string | null;
  rejectionReason: string | null;
}

/* The server enforces 6–64; mirrored here so a typo is caught before a round trip. */
const schema = z.object({
  reference: z
    .string()
    .trim()
    .min(6, zMsg("payment.reference_short", "Reference must be at least 6 characters"))
    .max(64, zMsg("payment.reference_long", "Reference is too long")),
  note: z.string().max(500).optional(),
});
type Values = z.infer<typeof schema>;

const inr = (paise: number) =>
  `₹${(paise / 100).toLocaleString("en-IN", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  })}`;

/* ───────────────────────────── Page ───────────────────────────── */

export default function PaperPaymentPage() {
  const paperId = useParams().id as string;
  const router = useRouter();
  const qc = useQueryClient();
  const [submitting, setSubmitting] = useState(false);

  const { data, isLoading, isError } = useQuery({
    queryKey: ["payment", "instructions", paperId],
    queryFn: async () => (await paymentApi.instructions(paperId)).data as Instructions,
  });

  const form = useForm<Values>({ resolver: zodResolver(schema) });

  async function onSubmit(values: Values) {
    try {
      setSubmitting(true);
      await paymentApi.declare(paperId, {
        reference: values.reference.trim(),
        note: values.note?.trim() || undefined,
      });
      await qc.invalidateQueries({ queryKey: ["payment", "instructions", paperId] });
      form.reset();
    } catch (err: unknown) {
      toast.error(
        (err as { response?: { data?: { message?: string } } })?.response?.data?.message ??
          "भुगतान विवरण भेजा नहीं जा सका / Could not submit the payment reference"
      );
    } finally {
      setSubmitting(false);
    }
  }

  if (isLoading) {
    return (
      <div className="flex min-h-[60vh] items-center justify-center">
        <Loader2 className="h-6 w-6 animate-spin text-gray-400" />
      </div>
    );
  }

  if (isError || !data) {
    return (
      <Shell>
        <Notice tone="red" icon={<AlertTriangle className="h-5 w-5" />}>
          यह पृष्ठ लोड नहीं हो सका।
          <br />
          <span className="text-gray-600">This page could not be loaded.</span>
        </Notice>
      </Shell>
    );
  }

  /* The editor has not set a UPI id yet. Refusing to render the form is
     deliberate — an author who pays to a blank payee has lost real money. */
  if (!data.configured) {
    return (
      <Shell referenceNo={data.paperReferenceNo}>
        <Notice tone="amber" icon={<AlertTriangle className="h-5 w-5" />}>
          भुगतान विवरण अभी उपलब्ध नहीं है। कृपया संपादक से संपर्क करें — आपका शोधपत्र
          सुरक्षित है।
          <br />
          <span className="text-gray-600">
            Payment details are not available yet. Please contact the editor — your paper
            is safe.
          </span>
        </Notice>
      </Shell>
    );
  }

  /* No fee is payable — either the editor has the payment section switched off,
     or this particular fee was cancelled when they switched it off.

     This must come before every other branch. Without it the page falls through
     to the form below and renders a working QR code for the editor's real UPI
     id: an author reaching this URL from an old link or a stale tab could send
     real money for a fee that no longer exists, and the declaration that would
     have recorded it is refused. */
  if (!data.enabled || data.paymentStatus === "CANCELLED") {
    return (
      <Shell referenceNo={data.paperReferenceNo}>
        <div className="py-6 text-center">
          <CheckCircle2 className="mx-auto mb-4 h-12 w-12 text-green-600" />
          <p className="text-gray-800">
            इस शोधपत्र पर कोई शुल्क देय नहीं है — यह समीक्षा प्रक्रिया में है।
          </p>
          <p className="mt-1 text-sm text-gray-500">
            No fee is payable for this paper. It is in the review process.
          </p>
          <p className="mt-4 text-xs text-gray-400">
            यदि आपने पहले ही भुगतान कर दिया है, तो कृपया संपादक से संपर्क करें।
            <br />
            If you have already paid, please contact the editor.
          </p>
          <button
            onClick={() => router.push(`/papers/${paperId}`)}
            className="mt-6 rounded-md bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700"
          >
            शोधपत्र देखें / View paper
          </button>
        </div>
      </Shell>
    );
  }

  if (data.paymentStatus === "SUCCESS") {
    return (
      <Shell referenceNo={data.paperReferenceNo}>
        <div className="text-center py-6">
          <CheckCircle2 className="mx-auto mb-4 h-12 w-12 text-green-600" />
          <p className="text-gray-800">भुगतान पुष्ट हो गया है — आपका शोधपत्र समीक्षा में है।</p>
          <p className="mt-1 text-sm text-gray-500">
            Your payment is confirmed and your paper has entered review.
          </p>
          <button
            onClick={() => router.push(`/papers/${paperId}`)}
            className="mt-6 rounded-md bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700"
          >
            शोधपत्र देखें / View paper
          </button>
        </div>
      </Shell>
    );
  }

  if (data.paymentStatus === "AWAITING_CONFIRMATION") {
    return (
      <Shell referenceNo={data.paperReferenceNo}>
        <div className="py-4 text-center">
          <Clock className="mx-auto mb-4 h-12 w-12 text-amber-500" />
          <p className="text-gray-800">
            आपका भुगतान विवरण मिल गया है और सत्यापन हेतु प्रतीक्षारत है।
          </p>
          <p className="mt-1 text-sm text-gray-500">
            We have your payment reference and are matching it against our records.
            This usually takes 1–2 working days.
          </p>

          <dl className="mx-auto mt-6 max-w-sm divide-y divide-gray-100 rounded-lg border border-gray-200 text-left text-sm">
            <Row label="रेफ़रेंस / Reference" value={data.declaredReference} mono />
            <Row label="राशि / Amount" value={inr(data.totalPaise)} />
          </dl>

          <p className="mt-6 text-xs text-gray-400">
            पुष्टि होते ही आपको ईमेल भेजा जाएगा।
            <br />
            You will get an email as soon as it is confirmed.
          </p>
        </div>
      </Shell>
    );
  }

  /* PENDING, or REJECTED and being corrected. */
  return (
    <Shell referenceNo={data.paperReferenceNo}>
      {data.paymentStatus === "REJECTED" && data.rejectionReason && (
        <Notice tone="red" icon={<AlertTriangle className="h-5 w-5" />}>
          <strong>भुगतान सत्यापित नहीं हो सका / Payment could not be verified</strong>
          <div className="mt-1">{data.rejectionReason}</div>
          <div className="mt-2 text-gray-600">
            आपका शोधपत्र सुरक्षित है — नीचे सही रेफ़रेंस नंबर दर्ज करें।
            <br />
            Your paper is safe. Enter the correct reference below.
          </div>
        </Notice>
      )}

      {/* ── Amount ── */}
      <div className="mb-6 rounded-lg border border-gray-200 bg-gray-50 p-4">
        <div className="flex justify-between text-sm text-gray-600">
          <span>समीक्षा शुल्क / Review fee</span>
          <span>{inr(data.amountPaise)}</span>
        </div>
        <div className="mt-1 flex justify-between text-sm text-gray-600">
          <span>GST</span>
          <span>{inr(data.gstPaise)}</span>
        </div>
        <div className="mt-2 flex justify-between border-t border-gray-200 pt-2 text-base font-semibold text-gray-900">
          <span>कुल / Total</span>
          <span>{inr(data.totalPaise)}</span>
        </div>
      </div>

      {/* ── Scan or pay ── */}
      <div className="grid gap-6 sm:grid-cols-2">
        <div className="text-center">
          <QrPanel value={data.upiLink} />
          <p className="mt-2 text-xs text-gray-500">
            किसी भी UPI ऐप से स्कैन करें
            <br />
            Scan with any UPI app
          </p>
          {/* On a phone the QR is useless — the camera and the payment app are the
              same device — so give a direct handoff instead. */}
          {data.upiLink && (
            <a
              href={data.upiLink}
              className="mt-3 inline-flex items-center gap-1.5 rounded-md border border-indigo-200 px-3 py-1.5 text-xs font-medium text-indigo-700 hover:bg-indigo-50 sm:hidden"
            >
              <Smartphone className="h-3.5 w-3.5" />
              UPI ऐप खोलें / Open UPI app
            </a>
          )}
        </div>

        <div className="space-y-3">
          <CopyField label="UPI आईडी / UPI ID" value={data.upiId} mono />
          <Field label="खाता / Payee" value={data.payeeName} />
          <CopyField
            label="भुगतान नोट में लिखें / Put in the payment note"
            value={data.paperReferenceNo}
            mono
          />
        </div>
      </div>

      {(data.instructionsHi || data.instructionsEn) && (
        <div className="mt-6 space-y-2 rounded-lg bg-indigo-50/60 p-4 text-sm text-gray-700">
          {data.instructionsHi && (
            <div dangerouslySetInnerHTML={{ __html: data.instructionsHi }} />
          )}
          {data.instructionsEn && (
            <div
              className="text-gray-600"
              dangerouslySetInnerHTML={{ __html: data.instructionsEn }}
            />
          )}
        </div>
      )}

      {/* ── Declaration ── */}
      <form onSubmit={form.handleSubmit(onSubmit)} className="mt-8 border-t border-gray-200 pt-6">
        <h2 className="text-sm font-semibold text-gray-900">
          भुगतान के बाद / After you have paid
        </h2>
        <p className="mt-1 text-xs text-gray-500">
          अपने UPI ऐप की सफलता स्क्रीन पर दिखने वाला <strong>UTR / रेफ़रेंस नंबर</strong> यहाँ
          दर्ज करें। यही नंबर हमारे बैंक विवरण में भी दिखता है।
          <br />
          Enter the <strong>UTR / reference number</strong> from your UPI app&apos;s success
          screen. That is the number that also appears on our bank statement.
        </p>

        <div className="mt-4">
          <label className="mb-1 block text-sm font-medium text-gray-700">
            UTR / रेफ़रेंस नंबर
          </label>
          <input
            className="w-full rounded-md border border-gray-300 px-3 py-2 font-mono text-sm shadow-sm placeholder:font-sans placeholder:text-gray-400 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
            placeholder="जैसे / e.g. 432198765012"
            {...form.register("reference")}
          />
          {form.formState.errors.reference && (
            <p className="mt-1 text-xs text-red-500">
              {form.formState.errors.reference.message}
            </p>
          )}
        </div>

        <div className="mt-3">
          <label className="mb-1 block text-sm font-medium text-gray-700">
            टिप्पणी (वैकल्पिक) / Note (optional)
          </label>
          <input
            className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm placeholder:text-gray-400 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
            placeholder="जैसे: PhonePe से, मेरे HDFC खाते से / e.g. Paid via PhonePe from my HDFC account"
            {...form.register("note")}
          />
        </div>

        <button
          type="submit"
          disabled={submitting}
          className="mt-5 inline-flex w-full items-center justify-center gap-2 rounded-md bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white shadow hover:bg-indigo-700 disabled:cursor-not-allowed disabled:opacity-50"
        >
          {submitting && <Loader2 className="h-4 w-4 animate-spin" />}
          भुगतान की सूचना दें / I have paid
        </button>

        <p className="mt-3 text-center text-xs text-gray-400">
          यह पुष्टि नहीं है — संपादक बैंक विवरण से मिलान करने के बाद पुष्टि करेंगे।
          <br />
          This is not a confirmation. The editor checks it against the bank statement first.
        </p>
      </form>
    </Shell>
  );
}

/* ───────────────────────────── Pieces ───────────────────────────── */

function Shell({
  children,
  referenceNo,
}: {
  children: React.ReactNode;
  referenceNo?: string | null;
}) {
  return (
    <div className="mx-auto max-w-2xl px-4 py-8">
      <Link
        href="/author"
        className="mb-4 inline-flex items-center gap-1 text-sm text-indigo-600 hover:underline"
      >
        <ArrowLeft className="h-4 w-4" />
        मेरे शोधपत्र / My papers
      </Link>

      <div className="rounded-xl border border-gray-200 bg-white p-6 shadow-sm">
        <h1 className="text-xl font-bold text-gray-900">समीक्षा शुल्क / Review fee</h1>
        {referenceNo && (
          <p className="mt-0.5 font-mono text-xs text-gray-500">{referenceNo}</p>
        )}
        <div className="mt-5">{children}</div>
      </div>
    </div>
  );
}

/** Rendered to a canvas in the browser; nothing is fetched for it. */
function QrPanel({ value }: { value: string | null }) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [failed, setFailed] = useState(false);

  useEffect(() => {
    if (!value || !canvasRef.current) return;
    QRCode.toCanvas(canvasRef.current, value, { width: 200, margin: 1 }).catch(() =>
      setFailed(true)
    );
  }, [value]);

  if (!value || failed) {
    // The UPI id beside this is still usable, so say that rather than
    // leaving a blank square.
    return (
      <div className="flex h-[200px] w-[200px] items-center justify-center rounded-lg border border-dashed border-gray-300 p-4 text-center text-xs text-gray-400">
        QR नहीं बन सका — कृपया UPI आईडी का उपयोग करें
        <br />
        QR unavailable — use the UPI ID
      </div>
    );
  }

  return (
    <canvas
      ref={canvasRef}
      className="mx-auto rounded-lg border border-gray-200 bg-white p-2"
    />
  );
}

function Field({ label, value }: { label: string; value: string | null }) {
  return (
    <div>
      <div className="text-xs text-gray-500">{label}</div>
      <div className="text-sm font-medium text-gray-900">{value || "—"}</div>
    </div>
  );
}

function CopyField({
  label,
  value,
  mono,
}: {
  label: string;
  value: string | null;
  mono?: boolean;
}) {
  return (
    <div>
      <div className="text-xs text-gray-500">{label}</div>
      <div className="flex items-center gap-1.5">
        <span
          className={cn("text-sm font-medium text-gray-900", mono && "font-mono")}
        >
          {value || "—"}
        </span>
        {value && (
          <button
            type="button"
            title="कॉपी करें / Copy"
            onClick={() => {
              navigator.clipboard?.writeText(value);
              toast.success("कॉपी हो गया / Copied");
            }}
            className="text-gray-400 hover:text-gray-700"
          >
            <Copy className="h-3.5 w-3.5" />
          </button>
        )}
      </div>
    </div>
  );
}

function Row({
  label,
  value,
  mono,
}: {
  label: string;
  value: string | null;
  mono?: boolean;
}) {
  return (
    <div className="flex justify-between px-4 py-2.5">
      <dt className="text-gray-500">{label}</dt>
      <dd className={cn("font-medium text-gray-900", mono && "font-mono")}>
        {value || "—"}
      </dd>
    </div>
  );
}

function Notice({
  children,
  tone,
  icon,
}: {
  children: React.ReactNode;
  tone: "red" | "amber";
  icon: React.ReactNode;
}) {
  const tones = {
    red: "border-red-200 bg-red-50 text-red-800",
    amber: "border-amber-200 bg-amber-50 text-amber-900",
  };
  return (
    <div className={cn("mb-6 flex items-start gap-2 rounded-md border p-3 text-sm", tones[tone])}>
      <span className="mt-0.5 shrink-0">{icon}</span>
      <div>{children}</div>
    </div>
  );
}
