"use client";

import { Suspense, useEffect, useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";
import { Eye, EyeOff, Loader2, Mail, ArrowLeft } from "lucide-react";
import { useAuth } from "@/lib/auth/AuthContext";
import { authApi } from "@/lib/api/auth";
import { ApiException } from "@/lib/api/client";
import { toast } from "sonner";
import PhoneOtpLogin from "./PhoneOtpLogin";

type Tab = "login" | "register";
type RegStep = "details" | "otp";

const DEFAULT_REDIRECT = "/dashboard";

/**
 * `?redirect=` target, accepted only as a same-origin relative path. Rejects
 * protocol-relative (`//evil.com`), backslash tricks (`/\evil.com`, which
 * browsers normalise to `//`) and control characters (the URL parser strips a
 * tab or newline, so `/<TAB>/evil.com` would become `//evil.com`).
 */
function safeRedirect(raw: string | null): string {
  if (!raw || !raw.startsWith("/") || raw.startsWith("//") || raw.startsWith("/\\")) return DEFAULT_REDIRECT;
  if (/[\u0000-\u001F\u007F\\]/.test(raw)) return DEFAULT_REDIRECT;
  return raw;
}

function LoginPageInner() {
  const router = useRouter();
  const search = useSearchParams();
  const justReset = search.get("reset") === "1";
  const redirectTo = safeRedirect(search.get("redirect"));
  const { login, register } = useAuth();

  const [tab, setTab] = useState<Tab>(() => (search.get("tab") === "register" ? "register" : "login"));
  // Email/password is the default way in; mobile + SMS code (4.7) is one tap away (?mode=otp).
  const [loginMode, setLoginMode] = useState<"otp" | "email">(() => (search.get("mode") === "otp" ? "otp" : "email"));
  const [notice, setNotice] = useState<string | null>(null);
  const [showPass, setShowPass] = useState(false);
  const [showConfirmPass, setShowConfirmPass] = useState(false);
  const [loading, setLoading] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);
  const [errors, setErrors] = useState<Record<string, string>>({});

  const [loginForm, setLoginForm] = useState({ email: "", password: "" });
  const [regForm, setRegForm] = useState({
    name: "",
    email: "",
    phone: "",
    password: "",
    password_confirmation: "",
  });
  const [regStep, setRegStep] = useState<RegStep>("details");
  const [otp, setOtp] = useState("");
  const [otpSending, setOtpSending] = useState(false);
  const [resendIn, setResendIn] = useState(0);

  useEffect(() => {
    if (resendIn <= 0) return;
    const t = setTimeout(() => setResendIn((s) => s - 1), 1000);
    return () => clearTimeout(t);
  }, [resendIn]);

  useEffect(() => {
    if (!justReset) return;
    toast.success("Password reset successful. Please sign in with your new password.");
  }, [justReset]);

  const inputClass =
    "w-full px-4 py-3 border border-gray-200 rounded-xl text-sm text-gray-900 placeholder:text-gray-400 bg-white focus:outline-none focus:ring-2 focus:ring-[#CC1414]/20 focus:border-[#CC1414]";

  function handleApiError(err: unknown) {
    if (err instanceof ApiException) {
      setFormError(err.message);
      const fieldErrors: Record<string, string> = {};
      if (err.errors) {
        for (const [field, msgs] of Object.entries(err.errors)) {
          if (msgs?.length) fieldErrors[field] = msgs[0];
        }
      }
      setErrors(fieldErrors);
    } else {
      setFormError("Something went wrong. Please try again.");
    }
  }

  async function onLogin(e: React.FormEvent) {
    e.preventDefault();
    setErrors({});
    setFormError(null);
    setLoading(true);
    try {
      await login(loginForm.email.trim(), loginForm.password);
      toast.success("Logged in successfully.");
      router.replace(redirectTo);
    } catch (err) {
      handleApiError(err);
    } finally {
      setLoading(false);
    }
  }

  async function onRegister(e: React.FormEvent) {
    e.preventDefault();
    setErrors({});
    setFormError(null);

    if (regForm.password !== regForm.password_confirmation) {
      setErrors({ password_confirmation: "Passwords do not match." });
      return;
    }
    if (!/^\d{6}$/.test(otp)) {
      setErrors({ otp: "Enter the 6-digit code sent to your email." });
      return;
    }

    setLoading(true);
    try {
      await register({
        name: regForm.name.trim(),
        email: regForm.email.trim(),
        password: regForm.password,
        password_confirmation: regForm.password_confirmation,
        phone: regForm.phone.trim() || undefined,
        otp,
      });
      toast.success("Account created successfully.");
      router.replace(redirectTo);
    } catch (err) {
      handleApiError(err);
    } finally {
      setLoading(false);
    }
  }

  async function sendOtp(isResend = false) {
    setErrors({});
    setFormError(null);

    if (!isResend) {
      // Validate details client-side before requesting an OTP.
      const fieldErrors: Record<string, string> = {};
      if (!regForm.name.trim()) fieldErrors.name = "Name is required.";
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(regForm.email.trim()))
        fieldErrors.email = "Enter a valid email.";
      if (regForm.phone && !/^\d{10}$/.test(regForm.phone))
        fieldErrors.phone = "Enter a valid 10-digit mobile.";
      if (regForm.password.length < 8 || !/[A-Za-z]/.test(regForm.password) || !/\d/.test(regForm.password))
        fieldErrors.password = "At least 8 chars with letters & numbers.";
      if (regForm.password !== regForm.password_confirmation)
        fieldErrors.password_confirmation = "Passwords do not match.";
      if (Object.keys(fieldErrors).length) {
        setErrors(fieldErrors);
        return;
      }
    }

    setOtpSending(true);
    try {
      await authApi.sendRegisterOtp(regForm.email.trim());
      setRegStep("otp");
      setResendIn(60);
      setNotice(
        isResend
          ? "A new verification code has been sent to your email."
          : `We've sent a 6-digit code to ${regForm.email.trim()}. It expires in 10 minutes.`
      );
      toast.success(isResend ? "A new verification code has been sent." : "Verification code sent to your email.");
    } catch (err) {
      handleApiError(err);
    } finally {
      setOtpSending(false);
    }
  }

  function backToDetails() {
    setRegStep("details");
    setOtp("");
    setErrors({});
    setFormError(null);
    setNotice(null);
  }

  return (
    <div className="min-h-screen bg-gradient-to-br from-gray-50 to-red-50 flex items-start justify-center px-4 pt-8 pb-10">
      <div className="w-full max-w-md">
        <div className="text-center mb-5">
          <Link href="/" className="inline-flex items-center">
            <Image src="/logo.png" alt="Biznie" width={220} height={58} className="h-12 w-auto" priority />
          </Link>
          <p className="text-gray-500 text-sm mt-2">India&apos;s B2B Raw Materials Platform</p>
        </div>

        <div className="bg-white rounded-2xl shadow-xl border border-gray-100 p-8">
          <div className="flex bg-gray-100 rounded-xl p-1 mb-6">
            <button
              type="button"
              onClick={() => { setTab("login"); setErrors({}); setFormError(null); setNotice(null); }}
              className={`flex-1 py-2.5 text-sm font-semibold rounded-lg transition-all ${
                tab === "login" ? "bg-white text-gray-900 shadow-sm" : "text-gray-500"
              }`}
            >
              Login
            </button>
            <button
              type="button"
              onClick={() => { setTab("register"); setErrors({}); setFormError(null); setNotice(null); setRegStep("details"); setOtp(""); }}
              className={`flex-1 py-2.5 text-sm font-semibold rounded-lg transition-all ${
                tab === "register" ? "bg-white text-gray-900 shadow-sm" : "text-gray-500"
              }`}
            >
              Register
            </button>
          </div>

          {/* A guest who started an RFQ is told why they are here and that
              nothing is lost (B15): the draft and the query string survive. */}
          {redirectTo.startsWith("/rfq") && !notice && (
            <div role="status" className="mb-4 rounded-lg bg-blue-50 border border-blue-100 px-4 py-2 text-sm text-blue-800">
              Please login or register to submit your RFQ — your selection is saved.
            </div>
          )}

          {notice && (
            <div className="mb-4 rounded-lg bg-green-50 border border-green-100 px-4 py-2 text-sm text-green-700">
              {notice}
            </div>
          )}

          {formError && (
            <div className="mb-4 rounded-lg bg-red-50 border border-red-100 px-4 py-2 text-sm text-red-700">
              {formError}
            </div>
          )}

          {tab === "login" && (
            <div role="tablist" aria-label="Login method" className="-mt-2 mb-4 flex justify-center gap-4 text-sm">
              {([
                ["email", "Email & password"],
                ["otp", "Mobile OTP"],
              ] as const).map(([value, label]) => (
                <button
                  key={value}
                  type="button"
                  role="tab"
                  aria-selected={loginMode === value}
                  onClick={() => { setLoginMode(value); setErrors({}); setFormError(null); }}
                  className={`border-b-2 pb-1 font-semibold transition ${
                    loginMode === value ? "border-[#CC1414] text-[#CC1414]" : "border-transparent text-gray-500 hover:text-gray-700"
                  }`}
                >
                  {label}
                </button>
              ))}
            </div>
          )}

          {tab === "login" && loginMode === "otp" ? (
            <PhoneOtpLogin
              inputClass={inputClass}
              onDone={(next) => {
                toast.success("Logged in successfully.");
                router.replace(next ?? redirectTo);
              }}
            />
          ) : tab === "login" ? (
            <form onSubmit={onLogin} className="space-y-4" noValidate>
              <Field label="Email" error={errors.email}>
                <input
                  required
                  type="email"
                  autoComplete="email"
                  placeholder="you@example.com"
                  value={loginForm.email}
                  onChange={(e) => setLoginForm({ ...loginForm, email: e.target.value })}
                  className={inputClass}
                />
              </Field>

              <Field label="Password" error={errors.password}>
                <div className="relative">
                  <input
                    required
                    type={showPass ? "text" : "password"}
                    autoComplete="current-password"
                    placeholder="Enter your password"
                    value={loginForm.password}
                    onChange={(e) => setLoginForm({ ...loginForm, password: e.target.value })}
                    className={`${inputClass} pr-12`}
                  />
                  <button
                    type="button"
                    onClick={() => setShowPass((v) => !v)}
                    className="absolute right-1 top-1/2 grid h-10 w-10 -translate-y-1/2 place-items-center text-gray-400 hover:text-gray-600"
                    aria-label={showPass ? "Hide password" : "Show password"}
                  >
                    {showPass ? <EyeOff size={15} /> : <Eye size={15} />}
                  </button>
                </div>
              </Field>

              <div className="flex justify-end -mt-2">
                <Link href="/forgot-password" className="text-xs font-semibold text-[#CC1414] hover:underline">
                  Forgot password?
                </Link>
              </div>

              <SubmitButton loading={loading} label="Login to Biznie" loadingLabel="Logging in..." />
            </form>
          ) : regStep === "details" ? (
            <form
              onSubmit={(e) => { e.preventDefault(); sendOtp(false); }}
              className="space-y-4"
              noValidate
            >
              <Field label="Full Name" error={errors.name}>
                <input
                  required
                  type="text"
                  autoComplete="name"
                  placeholder="Your name"
                  value={regForm.name}
                  onChange={(e) => setRegForm({ ...regForm, name: e.target.value })}
                  className={inputClass}
                />
              </Field>

              <Field label="Email" error={errors.email}>
                <input
                  required
                  type="email"
                  autoComplete="email"
                  placeholder="you@example.com"
                  value={regForm.email}
                  onChange={(e) => setRegForm({ ...regForm, email: e.target.value })}
                  className={inputClass}
                />
              </Field>

              <Field label="Mobile (optional)" error={errors.phone}>
                <input
                  type="tel"
                  inputMode="numeric"
                  autoComplete="tel"
                  placeholder="10-digit mobile"
                  value={regForm.phone}
                  onChange={(e) => setRegForm({ ...regForm, phone: e.target.value.replace(/\D/g, "").slice(0, 10) })}
                  className={inputClass}
                />
              </Field>

              <Field label="Password" error={errors.password} hint="At least 8 chars with letters & numbers.">
                <div className="relative">
                  <input
                    required
                    type={showPass ? "text" : "password"}
                    autoComplete="new-password"
                    placeholder="Create a password"
                    value={regForm.password}
                    onChange={(e) => setRegForm({ ...regForm, password: e.target.value })}
                    className={`${inputClass} pr-12`}
                  />
                  <button
                    type="button"
                    onClick={() => setShowPass((v) => !v)}
                    className="absolute right-1 top-1/2 grid h-10 w-10 -translate-y-1/2 place-items-center text-gray-400 hover:text-gray-600"
                    aria-label={showPass ? "Hide password" : "Show password"}
                  >
                    {showPass ? <EyeOff size={15} /> : <Eye size={15} />}
                  </button>
                </div>
              </Field>

              <Field label="Confirm Password" error={errors.password_confirmation}>
                <div className="relative">
                  <input
                    required
                    type={showConfirmPass ? "text" : "password"}
                    autoComplete="new-password"
                    placeholder="Re-enter your password"
                    value={regForm.password_confirmation}
                    onChange={(e) => setRegForm({ ...regForm, password_confirmation: e.target.value })}
                    className={`${inputClass} pr-12`}
                  />
                  <button
                    type="button"
                    onClick={() => setShowConfirmPass((v) => !v)}
                    className="absolute right-1 top-1/2 grid h-10 w-10 -translate-y-1/2 place-items-center text-gray-400 hover:text-gray-600"
                    aria-label={showConfirmPass ? "Hide password" : "Show password"}
                  >
                    {showConfirmPass ? <EyeOff size={15} /> : <Eye size={15} />}
                  </button>
                </div>
              </Field>

              <SubmitButton loading={otpSending} label="Send verification code" loadingLabel="Sending code..." />
            </form>
          ) : (
            <form onSubmit={onRegister} className="space-y-4" noValidate>
              <div className="rounded-lg bg-red-50/60 border border-red-100 px-4 py-3 text-sm text-gray-700 flex gap-2">
                <Mail size={16} className="mt-0.5 shrink-0 text-[#CC1414]" />
                <div className="flex-1">
                  <div>
                    A 6-digit code was sent to <strong>{regForm.email.trim()}</strong>.
                  </div>
                  <button
                    type="button"
                    onClick={backToDetails}
                    className="text-xs font-semibold text-[#CC1414] hover:underline inline-flex items-center gap-1 mt-1"
                  >
                    <ArrowLeft size={12} /> Change email
                  </button>
                </div>
              </div>

              <Field label="Verification code" error={errors.otp}>
                <input
                  required
                  type="text"
                  inputMode="numeric"
                  autoComplete="one-time-code"
                  placeholder="6-digit code"
                  maxLength={6}
                  value={otp}
                  onChange={(e) => setOtp(e.target.value.replace(/\D/g, "").slice(0, 6))}
                  className={`${inputClass} tracking-[0.5em] text-center font-bold text-lg`}
                />
              </Field>

              <div className="flex justify-between items-center -mt-2 text-xs">
                <span className="text-gray-400">Didn&apos;t get the code?</span>
                <button
                  type="button"
                  disabled={resendIn > 0 || otpSending}
                  onClick={() => sendOtp(true)}
                  className="font-semibold text-[#CC1414] hover:underline disabled:text-gray-300 disabled:no-underline disabled:cursor-not-allowed"
                >
                  {otpSending
                    ? "Sending..."
                    : resendIn > 0
                    ? `Resend in ${resendIn}s`
                    : "Resend code"}
                </button>
              </div>

              <SubmitButton loading={loading} label="Verify & Create Account" loadingLabel="Verifying..." />
            </form>
          )}

          <div className="mt-5 pt-5 border-t border-gray-100 text-center">
            <p className="text-xs text-gray-400">
              By continuing, you agree to our{" "}
              <Link href="/terms" className="text-[#CC1414] hover:underline">
                Terms &amp; Privacy Policy
              </Link>
            </p>
          </div>
        </div>
      </div>
    </div>
  );
}

function Field({
  label,
  error,
  hint,
  children,
}: {
  label: string;
  error?: string;
  hint?: string;
  children: React.ReactNode;
}) {
  return (
    <div>
      <label className="block text-xs font-semibold text-gray-500 mb-1.5 uppercase tracking-wide">{label}</label>
      {children}
      {hint && !error && <p className="text-[11px] text-gray-400 mt-1">{hint}</p>}
      {error && <p className="text-xs text-red-500 mt-1">{error}</p>}
    </div>
  );
}

function SubmitButton({ loading, label, loadingLabel }: { loading: boolean; label: string; loadingLabel: string }) {
  return (
    <button
      type="submit"
      disabled={loading}
      className="w-full bg-[#CC1414] hover:bg-[#A50E0E] disabled:opacity-70 text-white font-bold py-3.5 rounded-xl transition-colors text-sm flex items-center justify-center gap-2 shadow-md mt-2"
    >
      {loading ? (
        <>
          <Loader2 size={16} className="animate-spin" /> {loadingLabel}
        </>
      ) : (
        `${label} →`
      )}
    </button>
  );
}

export default function LoginPage() {
  return (
    <Suspense fallback={null}>
      <LoginPageInner />
    </Suspense>
  );
}
