"use client";

import {
  ClipboardEvent,
  FormEvent,
  KeyboardEvent,
  createContext,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { ArrowRight, CheckCircle2, Loader2, LogOut, X, Edit2 } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { apiBaseUrl, apiHeaders, apiPath } from "@/lib/api-url";

type AuthStep = "mobile" | "otp" | "profile" | "done";
type RequestStatus = "idle" | "loading" | "error";

export type CustomerUser = {
  id: number;
  name: string;
  email: string | null;
  mobile: string;
  profileImage?: string | null;
  isMobileVerified?: boolean;
  isEmailVerified?: boolean;
  status?: string;
  referralCode?: string | null;
};

type UserAuthContextValue = {
  user: CustomerUser | null;
  token: string;
  openAuthModal: () => void;
  updateUser: (user: CustomerUser) => void;
  logout: () => Promise<void>;
};

type VerifyOtpResponse = {
  authToken?: string;
  requiresRegistration?: boolean;
  user?: CustomerUser;
  error?: string;
};

type RegisterResponse = {
  user: CustomerUser;
};

const userAuthTokenKey = "userAuthToken";
const authSkipKey = "ride-n-revive-auth-skip";
const UserAuthContext = createContext<UserAuthContextValue | null>(null);

async function apiRequest<T>(path: string, init: RequestInit = {}) {
  const response = await fetch(`${apiBaseUrl}${apiPath(path)}`, {
    ...init,
    headers: apiHeaders({
      "Content-Type": "application/json",
      ...(init.headers ?? {}),
    }),
  });
  const data = (await response.json().catch(() => ({}))) as T & { error?: string };

  if (!response.ok) {
    throw new Error(data.error ?? "Request failed");
  }

  return data;
}

export function UserAuthProvider({ children }: { children: React.ReactNode }) {
  const [token, setToken] = useState("");
  const [user, setUser] = useState<CustomerUser | null>(null);
  const [isModalOpen, setIsModalOpen] = useState(false);

  useEffect(() => {
    const savedToken = window.localStorage.getItem(userAuthTokenKey);

    if (!savedToken) {
      setIsModalOpen(true);
      return;
    }

    apiRequest<{ user: CustomerUser }>("/api/auth/me", {
      headers: {
        Authorization: `Bearer ${savedToken}`,
      },
    })
      .then((data) => {
        setToken(savedToken);
        setUser(data.user);
      })
      .catch(() => {
        window.localStorage.removeItem(userAuthTokenKey);
        setIsModalOpen(true);
      });
  }, []);

  async function logout() {
    if (token) {
      await fetch(`${apiBaseUrl}${apiPath("/api/auth/logout")}`, {
        method: "POST",
        headers: apiHeaders({
          Authorization: `Bearer ${token}`,
        }),
      }).catch(() => undefined);
    }

    window.localStorage.removeItem(userAuthTokenKey);
    window.localStorage.removeItem(authSkipKey);
    setToken("");
    setUser(null);
    setIsModalOpen(true);
  }

  const contextValue = useMemo<UserAuthContextValue>(
    () => ({
      user,
      token,
      openAuthModal: () => setIsModalOpen(true),
      updateUser: setUser,
      logout,
    }),
    [token, user],
  );

  return (
    <UserAuthContext.Provider value={contextValue}>
      {children}
      {isModalOpen ? (
        <CustomerAuthModal
          token={token}
          user={user}
          onAuthenticated={(nextToken, nextUser) => {
            window.localStorage.setItem(userAuthTokenKey, nextToken);
            window.localStorage.removeItem(authSkipKey);
            setToken(nextToken);
            setUser(nextUser);
          }}
          onProfileSaved={setUser}
          onClose={() => setIsModalOpen(false)}
          onSkip={() => {
            window.localStorage.setItem(authSkipKey, "1");
            setIsModalOpen(false);
          }}
        />
      ) : null}
    </UserAuthContext.Provider>
  );
}

export function useUserAuth() {
  const context = useContext(UserAuthContext);

  if (!context) {
    throw new Error("useUserAuth must be used inside UserAuthProvider");
  }

  return context;
}

export function getUserAuthToken() {
  if (typeof window === "undefined") {
    return "";
  }

  return window.localStorage.getItem(userAuthTokenKey) ?? "";
}

function CustomerAuthModal({
  token,
  user,
  onAuthenticated,
  onProfileSaved,
  onClose,
  onSkip,
}: {
  token: string;
  user: CustomerUser | null;
  onAuthenticated: (token: string, user: CustomerUser) => void;
  onProfileSaved: (user: CustomerUser) => void;
  onClose: () => void;
  onSkip: () => void;
}) {
  const [step, setStep] = useState<AuthStep>(
    user && (!user.email || !user.name || user.name === "User")
      ? "profile"
      : user
        ? "done"
        : "mobile",
  );
  const [status, setStatus] = useState<RequestStatus>("idle");
  const [message, setMessage] = useState("");
  const [mobile, setMobile] = useState(user?.mobile ?? "");
  const [otp, setOtp] = useState("");
  const [askReferralCode, setAskReferralCode] = useState(false);
  const profileIncomplete = Boolean(user && (!user.email || !user.name || user.name === "User"));

  useEffect(() => {
    if (profileIncomplete) {
      setStep("profile");
    }
  }, [profileIncomplete]);

  async function requestOtp(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setStatus("loading");
    setMessage("");

    try {
      await apiRequest("/api/auth/request-otp", {
        method: "POST",
        body: JSON.stringify({ mobile }),
      });
      setStep("otp");
      setStatus("idle");
    } catch (error) {
      setStatus("error");
      setMessage(error instanceof Error ? error.message : "Could not send OTP");
    }
  }

  async function verifyOtp(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setStatus("loading");
    setMessage("");

    try {
      const data = await apiRequest<VerifyOtpResponse>("/api/auth/verify-otp", {
        method: "POST",
        body: JSON.stringify({
          mobile,
          otp,
          deviceName: navigator.userAgent.includes("Mobile") ? "Mobile browser" : "Web browser",
        }),
      });

      if (!data.authToken || !data.user) {
        throw new Error("Login failed");
      }

      onAuthenticated(data.authToken, data.user);
      setAskReferralCode(Boolean(data.requiresRegistration));
      setStep(data.requiresRegistration ? "profile" : "done");
      setStatus("idle");
    } catch (error) {
      setStatus("error");
      setMessage(error instanceof Error ? error.message : "Could not verify OTP");
    }
  }

  async function saveProfile(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setStatus("loading");
    setMessage("");

    const formData = new FormData(event.currentTarget);

    try {
      const data = await apiRequest<RegisterResponse>("/api/auth/register", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token || (window.localStorage.getItem(userAuthTokenKey) ?? "")}`,
        },
        body: JSON.stringify({
          name: String(formData.get("name") ?? ""),
          email: String(formData.get("email") ?? ""),
          referralCode: String(formData.get("referralCode") ?? ""),
        }),
      });

      onProfileSaved(data.user);
      setStep("done");
      setStatus("idle");
    } catch (error) {
      setStatus("error");
      setMessage(error instanceof Error ? error.message : "Could not save profile");
    }
  }

  return (
    <div className="fixed inset-0 z-[90] grid place-items-center bg-foreground/65 p-4 font-['Space_Grotesk'] backdrop-blur-md transition-all">
      <div className="relative w-full max-w-[440px] overflow-hidden rounded-[2rem] bg-card shadow-2xl ring-1 ring-border animate-in fade-in zoom-in-95 duration-200">
        {/* Close Button */}
        <button
          type="button"
          onClick={onClose}
          className="absolute right-5 top-6 rounded-full bg-accent p-2 text-muted-foreground transition-colors hover:bg-primary hover:text-primary-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
          aria-label="Close"
        >
          <X className="h-4 w-4" />
        </button>

        <div className="px-8 pb-8 pt-12">
          {/* Logo & Title Center */}
          <div className="mb-8 flex flex-col items-center text-center">
            <div className="relative mb-5 flex h-20 w-20 items-center justify-center rounded-2xl bg-background shadow-[0_8px_30px_rgba(211,47,47,0.12)] ring-1 ring-border">
              <Image
                src="/images/new-logo.png"
                alt="Ride N Revive"
                fill
                sizes="80px"
                className="object-contain p-3"
              />
            </div>
            <h2 className="text-2xl font-black tracking-tight text-foreground">
              {step === "mobile" && "Welcome Back"}
              {step === "otp" && "Check Your Phone"}
              {step === "profile" && "Complete Profile"}
              {step === "done" && "You're All Set!"}
            </h2>
            <p className="mt-2 text-sm font-medium text-muted-foreground">
              {step === "mobile" && "Enter your mobile number to access your garage and orders."}
              {step === "otp" && "We've sent a 5-digit secure code to your device."}
              {step === "profile" && "Just a few more details to set up your account."}
              {step === "done" && "Your account has been securely verified."}
            </p>
          </div>

          {/* Forms */}
          <div className="relative">
            {step === "mobile" ? (
              <form onSubmit={requestOtp} className="space-y-4">
                <div className="relative">
                  <span className="absolute left-4 top-1/2 -translate-y-1/2 text-sm font-bold text-muted-foreground">
                    +91
                  </span>
                  <input
                    required
                    value={mobile}
                    onChange={(event) => setMobile(event.target.value)}
                    placeholder="Enter 10-digit number"
                    className="h-12 w-full rounded-lg border border-border bg-background px-12 text-base font-semibold text-foreground outline-none transition placeholder:text-muted-foreground/70 focus:border-primary focus:ring-2 focus:ring-primary/20"
                  />
                </div>
                <SubmitButton loading={status === "loading"} label="Continue" />
                <button
                  type="button"
                  onClick={onSkip}
                  className="mt-2 block w-full py-3 text-center text-sm font-bold text-muted-foreground transition-colors hover:text-primary"
                >
                  Skip and browse services
                </button>
              </form>
            ) : null}

            {step === "otp" ? (
              <form onSubmit={verifyOtp} className="space-y-6">
                <div className="flex items-center justify-center gap-2 rounded-xl bg-accent py-3">
                  <span className="text-sm font-bold text-foreground">+91 {mobile}</span>
                  <button
                    type="button"
                    onClick={() => setStep("mobile")}
                    className="flex h-6 w-6 items-center justify-center rounded-full bg-background text-muted-foreground transition-colors hover:bg-primary hover:text-primary-foreground"
                    title="Edit number"
                  >
                    <Edit2 className="h-3 w-3" />
                  </button>
                </div>

                <OtpFields value={otp} onChange={setOtp} />
                <SubmitButton loading={status === "loading"} label="Verify Secure Code" />
              </form>
            ) : null}

            {step === "profile" ? (
              <form onSubmit={saveProfile} className="space-y-4">
                <AuthField
                  label="Full Name"
                  name="name"
                  defaultValue={user?.name === "User" ? "" : user?.name}
                  placeholder="John Doe"
                />
                <AuthField
                  label="Email Address"
                  name="email"
                  type="email"
                  defaultValue={user?.email ?? ""}
                  placeholder="john@example.com"
                />
                {askReferralCode || !user?.referralCode ? (
                  <AuthField
                    label="Referral Code"
                    name="referralCode"
                    required={false}
                    placeholder="Optional"
                  />
                ) : null}
                <div className="pt-2">
                  <SubmitButton loading={status === "loading"} label="Save Details" />
                </div>
              </form>
            ) : null}

            {step === "done" ? (
              <div className="flex flex-col items-center">
                <div className="mb-6 grid h-20 w-20 place-items-center rounded-full bg-emerald-100 text-emerald-500 ring-8 ring-emerald-50">
                  <CheckCircle2 className="h-10 w-10" />
                </div>
                <button
                  type="button"
                  onClick={onClose}
                  className="inline-flex h-12 w-full items-center justify-center gap-2 rounded-lg bg-primary px-5 text-sm font-semibold text-primary-foreground shadow-elegant transition hover:opacity-95 focus:outline-none focus:ring-2 focus:ring-primary/20 active:scale-[0.98]"
                >
                  Enter Garage
                </button>
              </div>
            ) : null}

            {message ? (
              <div
                className={`mt-6 rounded-xl p-4 text-center text-sm font-bold ${
                  status === "error"
                    ? "bg-red-50 text-red-600 ring-1 ring-inset ring-red-100"
                    : "bg-emerald-50 text-emerald-700 ring-1 ring-inset ring-emerald-100"
                }`}
              >
                {message}
              </div>
            ) : null}
          </div>
        </div>
      </div>
    </div>
  );
}

function SubmitButton({ loading, label }: { loading: boolean; label: string }) {
  return (
    <button
      type="submit"
      disabled={loading}
      className="inline-flex h-12 w-full items-center justify-center gap-2 rounded-lg bg-primary px-5 text-sm font-semibold text-primary-foreground shadow-elegant transition hover:opacity-95 focus:outline-none focus:ring-2 focus:ring-primary/20 active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-70 disabled:active:scale-100"
    >
      {loading ? (
        <Loader2 className="h-5 w-5 animate-spin" />
      ) : (
        <>
          {label}
          <ArrowRight className="h-5 w-5" />
        </>
      )}
    </button>
  );
}

function OtpFields({ value, onChange }: { value: string; onChange: (value: string) => void }) {
  const inputRefs = useRef<Array<HTMLInputElement | null>>([]);
  const digits = Array.from({ length: 5 }, (_, index) => value[index] ?? "");

  function setDigit(index: number, nextValue: string) {
    const digit = nextValue.replace(/\D/g, "").slice(-1);
    const nextDigits = [...digits];
    nextDigits[index] = digit;
    onChange(nextDigits.join(""));

    if (digit && index < inputRefs.current.length - 1) {
      inputRefs.current[index + 1]?.focus();
    }
  }

  function handleKeyDown(index: number, event: KeyboardEvent<HTMLInputElement>) {
    if (event.key === "Backspace" && !digits[index] && index > 0) {
      inputRefs.current[index - 1]?.focus();
    }
  }

  function handlePaste(event: ClipboardEvent<HTMLInputElement>) {
    event.preventDefault();
    const pastedDigits = event.clipboardData.getData("text").replace(/\D/g, "").slice(0, 5);

    if (pastedDigits) {
      onChange(pastedDigits);
      inputRefs.current[Math.min(pastedDigits.length, 5) - 1]?.focus();
    }
  }

  return (
    <div className="grid grid-cols-5 gap-2">
      {digits.map((digit, index) => (
        <input
          key={index}
          ref={(element) => {
            inputRefs.current[index] = element;
          }}
          required
          inputMode="numeric"
          pattern="[0-9]*"
          maxLength={1}
          value={digit}
          onChange={(event) => setDigit(index, event.target.value)}
          onKeyDown={(event) => handleKeyDown(index, event)}
          onPaste={handlePaste}
          className="h-12 rounded-lg border border-border bg-background text-center text-xl font-black text-foreground outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/20"
          aria-label={`OTP digit ${index + 1}`}
        />
      ))}
    </div>
  );
}

function UserAvatar({ user, className = "h-8 w-8" }: { user: CustomerUser; className?: string }) {
  const label = (user.name && user.name !== "User" ? user.name : user.mobile).slice(0, 1);

  return (
    <span
      className={`relative grid shrink-0 place-items-center overflow-hidden rounded-full bg-primary/10 text-xs font-black uppercase text-primary ring-1 ring-border ${className}`}
    >
      {user.profileImage ? (
        <img src={user.profileImage} alt="" className="h-full w-full object-cover" />
      ) : (
        label
      )}
    </span>
  );
}

function AuthField({
  label,
  name,
  type = "text",
  defaultValue,
  placeholder,
  required = true,
}: {
  label: string;
  name: string;
  type?: string;
  defaultValue?: string;
  placeholder?: string;
  required?: boolean;
}) {
  return (
    <div className="space-y-1.5">
      <label
        htmlFor={name}
        className="block text-xs font-bold uppercase tracking-wider text-muted-foreground"
      >
        {label}
      </label>
      <input
        id={name}
        required={required}
        name={name}
        type={type}
        defaultValue={defaultValue}
        placeholder={placeholder}
        className="h-12 w-full rounded-lg border border-border bg-background px-4 text-sm font-semibold text-foreground outline-none transition placeholder:text-muted-foreground/70 focus:border-primary focus:ring-2 focus:ring-primary/20"
      />
    </div>
  );
}

export function CustomerAccountButton({ mobile = false }: { mobile?: boolean }) {
  const { user, openAuthModal, logout } = useUserAuth();

  if (!user) {
    return (
      <button
        type="button"
        onClick={openAuthModal}
        className={
          mobile
            ? "flex w-full items-center rounded-xl px-3 py-2.5 text-sm font-bold transition-colors hover:bg-accent"
            : "hidden h-10 items-center rounded-full border border-border/70 bg-background/70 px-4 text-sm font-bold text-foreground/70 transition hover:bg-accent hover:text-foreground sm:inline-flex"
        }
      >
        Login
      </button>
    );
  }

  if (mobile) {
    return (
      <div className="mt-2 grid grid-cols-[1fr_auto] gap-2 border-t border-border/70 pt-2">
        <Link
          href="/account"
          className="inline-flex min-w-0 items-center gap-2 rounded-xl px-3 py-2.5 text-sm font-bold transition-colors hover:bg-accent"
          title={user.mobile}
        >
          <UserAvatar user={user} />
          {user.name && user.name !== "User" ? user.name : "Account"}
        </Link>
        <button
          type="button"
          onClick={logout}
          className="grid h-10 w-10 place-items-center rounded-xl border border-border/70 text-foreground/70 transition hover:bg-accent hover:text-foreground"
          aria-label="Logout"
        >
          <LogOut className="h-4 w-4" />
        </button>
      </div>
    );
  }

  return (
    <div className="hidden items-center gap-2 sm:flex">
      <Link
        href="/account"
        className="inline-flex h-10 items-center gap-2 rounded-full border border-border/70 bg-background/70 py-1 pl-1 pr-4 text-sm font-bold text-foreground/70 transition hover:bg-accent hover:text-foreground"
        title={user.mobile}
      >
        <UserAvatar user={user} />
        {user.name && user.name !== "User" ? user.name : "Account"}
      </Link>
      <button
        type="button"
        onClick={logout}
        className="grid h-10 w-10 place-items-center rounded-full border border-border/70 bg-background/70 text-foreground/70 transition hover:bg-accent hover:text-foreground"
        aria-label="Logout"
      >
        <LogOut className="h-4 w-4" />
      </button>
    </div>
  );
}
