"use client";

import { useEffect, useState } from "react";
import { Loader2, Smartphone } from "lucide-react";
import { authApi } from "@/lib/api/auth";
import { ApiException } from "@/lib/api/client";
import { useAuth } from "@/lib/auth/AuthContext";
import { MESSAGES, isGstin, isMobile, normalizeMobile } from "@/lib/validation";

type Step = "phone" | "code";

/**
 * Sign in — or sign up on first use — with a mobile number and an SMS code
 * (4.7). A known number just needs the code; a new one also gives a name and
 * whether they buy or sell (optional company and GSTIN). "Seller" lands on the
 * seller application, which is where selling is approved.
 */
export default function PhoneOtpLogin({
  inputClass,
  onDone,
}: {
  inputClass: string;
  /** Called with where to go next (the seller application for new sellers). */
  onDone: (next: string | null) => void;
}) {
  const { loginWithToken } = useAuth();
  const [step, setStep] = useState<Step>("phone");
  const [phone, setPhone] = useState("");
  const [code, setCode] = useState("");
  const [registered, setRegistered] = useState(true);
  const [devCode, setDevCode] = useState<string | null>(null);
  const [profile, setProfile] = useState({ name: "", role: "buyer" as "buyer" | "seller", company_name: "", gst_number: "", email: "" });
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [error, setError] = useState<string | null>(null);
  const [info, setInfo] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const [resendIn, setResendIn] = useState(0);

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

  function showApiError(err: unknown) {
    if (err instanceof ApiException) {
      setError(err.message);
      const fe: Record<string, string> = {};
      for (const [k, m] of Object.entries(err.errors ?? {})) if (m?.[0]) fe[k] = m[0];
      setErrors(fe);
    } else {
      setError("Something went wrong. Please try again.");
    }
  }

  async function send(e?: React.FormEvent) {
    e?.preventDefault();
    setError(null);
    setErrors({});
    const mobile = normalizeMobile(phone);
    if (!isMobile(mobile)) {
      setErrors({ phone: MESSAGES.mobile });
      return;
    }
    setBusy(true);
    try {
      const res = await authApi.sendPhoneOtp(mobile);
      setPhone(mobile);
      setRegistered(res.is_registered);
      setDevCode(res.debug_otp ?? null);
      setInfo(res.message);
      setStep("code");
      setResendIn(60);
    } catch (err) {
      showApiError(err);
    } finally {
      setBusy(false);
    }
  }

  async function verify(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    const fe: Record<string, string> = {};
    if (!/^\d{6}$/.test(code)) fe.otp = "Enter the 6-digit code";
    if (!registered) {
      if (!profile.name.trim()) fe.name = "Enter your name";
      if (profile.gst_number && !isGstin(profile.gst_number)) fe.gst_number = MESSAGES.gstin;
    }
    setErrors(fe);
    if (Object.keys(fe).length) return;

    setBusy(true);
    try {
      const res = await authApi.verifyPhoneOtp({
        phone,
        otp: code,
        ...(registered
          ? {}
          : {
              name: profile.name.trim(),
              role: profile.role,
              company_name: profile.company_name.trim() || undefined,
              gst_number: profile.gst_number.trim().toUpperCase() || undefined,
              email: profile.email.trim() || undefined,
            }),
      });
      loginWithToken(res.token, res.user);
      onDone(res.next ?? null);
    } catch (err) {
      showApiError(err);
      setBusy(false);
    }
  }

  const err = (k: string) => (errors[k] ? <p className="mt-1 text-xs text-red-600">{errors[k]}</p> : null);

  if (step === "phone") {
    return (
      <form onSubmit={send} className="space-y-4" noValidate>
        <div>
          <label htmlFor="otp-phone" className="mb-1.5 block text-sm font-medium text-gray-700">Mobile number</label>
          <div className="flex">
            <span className="inline-flex items-center rounded-l-xl border border-r-0 border-gray-200 bg-gray-50 px-3 text-sm text-gray-500">+91</span>
            <input
              id="otp-phone"
              type="tel"
              inputMode="numeric"
              autoComplete="tel-national"
              placeholder="10-digit mobile"
              value={phone}
              onChange={(e) => setPhone(e.target.value.replace(/[^\d+ ]/g, ""))}
              className={`${inputClass} rounded-l-none`}
            />
          </div>
          {err("phone")}
        </div>
        {error && <p className="rounded-lg bg-red-50 px-3 py-2 text-sm text-red-700">{error}</p>}
        <button type="submit" disabled={busy} className="flex w-full items-center justify-center gap-2 rounded-xl bg-[#CC1414] py-3 text-sm font-bold text-white hover:bg-[#A50E0E] disabled:opacity-60">
          {busy ? <Loader2 size={16} className="animate-spin" /> : <Smartphone size={16} />} {busy ? "Sending…" : "Send code"}
        </button>
        <p className="text-center text-xs text-gray-500">New to Biznie? The same code creates your account.</p>
      </form>
    );
  }

  return (
    <form onSubmit={verify} className="space-y-4" noValidate>
      {info && <p className="rounded-lg bg-green-50 px-3 py-2 text-sm text-green-700">{info}</p>}
      {devCode && (
        <p className="rounded-lg bg-amber-50 px-3 py-2 text-xs text-amber-800">Local environment, no SMS sent. Code: <b>{devCode}</b></p>
      )}
      <div>
        <label htmlFor="otp-code" className="mb-1.5 block text-sm font-medium text-gray-700">6-digit code</label>
        <input
          id="otp-code"
          inputMode="numeric"
          autoComplete="one-time-code"
          maxLength={6}
          value={code}
          onChange={(e) => setCode(e.target.value.replace(/\D/g, ""))}
          className={`${inputClass} tracking-[0.4em]`}
        />
        {err("otp")}
      </div>

      {!registered && (
        <div className="space-y-3 rounded-xl border border-gray-100 bg-gray-50 p-4">
          <p className="text-sm font-semibold text-gray-900">Create your account</p>
          <div>
            <label htmlFor="otp-name" className="mb-1 block text-xs font-medium text-gray-700">Your name</label>
            <input id="otp-name" value={profile.name} onChange={(e) => setProfile({ ...profile, name: e.target.value })} className={inputClass} />
            {err("name")}
          </div>
          <fieldset>
            <legend className="mb-1 text-xs font-medium text-gray-700">I want to</legend>
            <div className="grid grid-cols-2 gap-2">
              {([
                ["buyer", "Buy materials"],
                ["seller", "Sell materials"],
              ] as const).map(([value, label]) => (
                <label
                  key={value}
                  className={`cursor-pointer rounded-lg border px-3 py-2 text-center text-sm font-medium ${
                    profile.role === value ? "border-[#CC1414] bg-red-50 text-[#CC1414]" : "border-gray-200 bg-white text-gray-700"
                  }`}
                >
                  <input type="radio" name="role" value={value} checked={profile.role === value} onChange={() => setProfile({ ...profile, role: value })} className="sr-only" />
                  {label}
                </label>
              ))}
            </div>
            {err("role")}
          </fieldset>
          <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
            <div>
              <label htmlFor="otp-company" className="mb-1 block text-xs font-medium text-gray-700">Company (optional)</label>
              <input id="otp-company" value={profile.company_name} onChange={(e) => setProfile({ ...profile, company_name: e.target.value })} className={inputClass} />
            </div>
            <div>
              <label htmlFor="otp-gst" className="mb-1 block text-xs font-medium text-gray-700">GSTIN (optional)</label>
              <input
                id="otp-gst"
                value={profile.gst_number}
                onChange={(e) => setProfile({ ...profile, gst_number: e.target.value.toUpperCase() })}
                maxLength={15}
                className={inputClass}
              />
              {err("gst_number")}
            </div>
          </div>
          <div>
            <label htmlFor="otp-email" className="mb-1 block text-xs font-medium text-gray-700">Email (optional, for invoices)</label>
            <input id="otp-email" type="email" value={profile.email} onChange={(e) => setProfile({ ...profile, email: e.target.value })} className={inputClass} />
            {err("email")}
          </div>
        </div>
      )}

      {error && <p className="rounded-lg bg-red-50 px-3 py-2 text-sm text-red-700">{error}</p>}
      <button type="submit" disabled={busy} className="flex w-full items-center justify-center gap-2 rounded-xl bg-[#CC1414] py-3 text-sm font-bold text-white hover:bg-[#A50E0E] disabled:opacity-60">
        {busy && <Loader2 size={16} className="animate-spin" />}
        {registered ? "Verify & login" : "Verify & create account"}
      </button>
      <div className="flex items-center justify-between text-xs">
        <button type="button" onClick={() => { setStep("phone"); setCode(""); setError(null); }} className="font-semibold text-gray-600 hover:text-gray-900">
          Change number
        </button>
        <button type="button" disabled={resendIn > 0 || busy} onClick={() => send()} className="font-semibold text-[#CC1414] disabled:text-gray-400">
          {resendIn > 0 ? `Resend in ${resendIn}s` : "Resend code"}
        </button>
      </div>
    </form>
  );
}
