"use client";

import { useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { motion } from "framer-motion";
import { ImageUp, Hash, X, AlertCircle } from "lucide-react";
import { TopBar } from "@/components/ui/TopBar";
import { Button } from "@/components/ui/Button";
import { useOrderStore } from "@/lib/order-store";
import { OrderSubmissionError } from "@/lib/data/orders";
import { useTranslation } from "@/lib/i18n/LanguageProvider";

const MAX_FILE_BYTES = 10 * 1024 * 1024; // 10MB, matches the hint text below
const ACCEPTED_TYPES = ["image/png", "image/jpeg", "image/jpg", "image/webp"];

export default function UploadScreenshotPage() {
  const router = useRouter();
  const { t } = useTranslation();
  const { draft, hydrated, setDraft, submitDraft } = useOrderStore();
  const [txnId, setTxnId] = useState(draft.txnId);
  const [preview, setPreview] = useState<string | null>(draft.screenshotPreviewUrl);
  const [fileError, setFileError] = useState<string | null>(null);
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  // txnId/preview's initial values above are whatever was there before
  // hydration finished loading (usually empty/null) — sync them
  // explicitly once a persisted draft loads in after mount, same
  // reasoning as payment-methods page's `selected` sync.
  useEffect(() => {
    if (!hydrated) return;
    if (draft.txnId && !txnId) setTxnId(draft.txnId);
    if (draft.screenshotPreviewUrl && !preview) setPreview(draft.screenshotPreviewUrl);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [hydrated]);

  useEffect(() => {
    // Wait for hydration — see payment-methods/page.tsx's identical
    // comment on why checking draft.pkg/paymentMethod before that
    // finishes would bounce someone with a perfectly good draft.
    if (!hydrated) return;
    if (!draft.pkg || !draft.paymentMethod) {
      router.replace("/packages");
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [hydrated, draft.pkg, draft.paymentMethod]);

  // Revoke the blob URL when it's replaced or the page unmounts, so we
  // don't leak memory across a multi-step form the user might revisit.
  useEffect(() => {
    return () => {
      if (preview) URL.revokeObjectURL(preview);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  function handleFile(file: File | undefined) {
    if (!file) return;
    setFileError(null);

    if (!ACCEPTED_TYPES.includes(file.type)) {
      setFileError(t("uploadScreenshot.invalidType"));
      return;
    }
    if (file.size > MAX_FILE_BYTES) {
      setFileError(t("uploadScreenshot.tooLarge"));
      return;
    }

    if (preview) URL.revokeObjectURL(preview);
    const url = URL.createObjectURL(file);
    setPreview(url);
    setDraft({ screenshotFile: file, screenshotPreviewUrl: url });
  }

  function handleRemove() {
    if (preview) URL.revokeObjectURL(preview);
    setPreview(null);
    setDraft({ screenshotFile: null, screenshotPreviewUrl: null });
  }

  const canSubmit = txnId.trim().length >= 6 && !!draft.screenshotFile && !submitting;

  async function handleSubmit() {
    if (!canSubmit) return;
    setSubmitError(null);
    setSubmitting(true);

    const finalTxnId = txnId.trim();
    setDraft({ txnId: finalTxnId });

    try {
      // Pass the just-typed value directly rather than relying on the
      // setDraft above having landed — see the comment on submitDraft's
      // signature in lib/order-store.tsx for why that matters.
      const order = await submitDraft({ txnId: finalTxnId });
      router.push(`/order-submitted?orderId=${order.orderNumber}`);
    } catch (err) {
      setSubmitting(false);
      const code = err instanceof OrderSubmissionError ? err.code : null;
      setSubmitError(
        code === "AUTH_REQUIRED"
          ? t("uploadScreenshot.authRequired")
          : code === "ORDER_INCOMPLETE"
          ? t("uploadScreenshot.orderIncomplete")
          : code === "PACKAGE_UNAVAILABLE"
          ? t("uploadScreenshot.packageUnavailable")
          : code === "PAYMENT_METHOD_UNAVAILABLE"
          ? t("uploadScreenshot.paymentMethodUnavailable")
          : code === "TOO_SOON"
          ? t("uploadScreenshot.tooSoon")
          : t("uploadScreenshot.genericError")
      );
    }
  }

  return (
    <div className="flex flex-1 flex-col">
      <TopBar title={t("uploadScreenshot.title")} />

      <div className="flex flex-1 flex-col gap-6 px-4 pb-6 pt-2">
        <div>
          <label className="mb-2 block text-sm font-medium text-muted">
            {t("uploadScreenshot.transactionId")}
          </label>
          <div className="flex items-center gap-3 rounded-2xl glass px-4 py-3.5">
            <Hash size={17} className="text-muted" strokeWidth={2} />
            <input
              value={txnId}
              onChange={(e) => setTxnId(e.target.value)}
              placeholder="e.g. EP849213705"
              className="w-full bg-transparent font-mono text-[15px] outline-none placeholder:font-body placeholder:text-muted"
            />
          </div>
        </div>

        <div>
          <label className="mb-2 block text-sm font-medium text-muted">
            {t("uploadScreenshot.screenshot")}
          </label>
          <input
            ref={fileRef}
            type="file"
            accept="image/png,image/jpeg,image/webp"
            className="hidden"
            onChange={(e) => handleFile(e.target.files?.[0])}
          />
          {preview ? (
            <div className="relative overflow-hidden rounded-3xl glass p-2">
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={preview}
                alt="Payment screenshot preview"
                className="max-h-72 w-full rounded-2xl object-cover"
              />
              <button
                type="button"
                onClick={handleRemove}
                aria-label="Remove screenshot"
                className="absolute right-4 top-4 flex h-8 w-8 items-center justify-center rounded-full bg-ink/70 text-paper backdrop-blur"
              >
                <X size={15} strokeWidth={2.5} />
              </button>
            </div>
          ) : (
            <motion.button
              type="button"
              whileTap={{ scale: 0.98 }}
              onClick={() => fileRef.current?.click()}
              className="flex w-full flex-col items-center gap-3 rounded-3xl border-2 border-dashed border-ink/15 px-4 py-10 text-center dark:border-white/15"
            >
              <span className="flex h-12 w-12 items-center justify-center rounded-2xl bg-gold/15">
                <ImageUp size={20} className="text-gold-dim dark:text-gold-bright" strokeWidth={2} />
              </span>
              <div>
                <p className="text-sm font-semibold">{t("uploadScreenshot.tapToUpload")}</p>
                <p className="mt-1 text-xs text-muted">{t("uploadScreenshot.fileHint")}</p>
              </div>
            </motion.button>
          )}
          {fileError && (
            <p className="mt-2 flex items-center gap-1.5 text-xs text-danger">
              <AlertCircle size={13} /> {fileError}
            </p>
          )}
        </div>

        {submitError && (
          <div className="flex items-start gap-2 rounded-xl bg-danger/10 px-3.5 py-3 text-sm text-danger">
            <AlertCircle size={16} className="mt-0.5 shrink-0" />
            {submitError}
          </div>
        )}

        <div className="mt-auto">
          <Button size="lg" fullWidth disabled={!canSubmit} onClick={handleSubmit}>
            {submitting ? t("uploadScreenshot.submitting") : t("uploadScreenshot.submitOrder")}
          </Button>
        </div>
      </div>
    </div>
  );
}
