"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";

export type Customer = {
  id: string;
  email: string;
  first_name: string | null;
  last_name: string | null;
  phone: string | null;
  created_at: string;
};

type AuthState = {
  customer: Customer | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (email: string, password: string) => Promise<void>;
  register: (data: {
    email: string;
    password: string;
    first_name: string;
    last_name: string;
  }) => Promise<void>;
  logout: () => Promise<void>;
  refreshCustomer: () => Promise<void>;
};

const AuthContext = createContext<AuthState | null>(null);

async function apiJson<T>(url: string, init?: RequestInit): Promise<T> {
  const res = await fetch(url, {
    ...init,
    headers: { "Content-Type": "application/json", ...init?.headers },
  });
  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    const msg = body?.error ?? `Auth API error: ${res.status}`;
    throw new Error(msg);
  }
  return res.json();
}

export function AuthProvider({ children }: { children: ReactNode }) {
  const [customer, setCustomer] = useState<Customer | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  // On mount: check if user is already authenticated via cookie
  useEffect(() => {
    async function checkAuth() {
      try {
        const data = await apiJson<{ customer: Customer }>("/api/account/me");
        setCustomer(data.customer);
      } catch {
        setCustomer(null);
      } finally {
        setIsLoading(false);
      }
    }
    checkAuth();
  }, []);

  const login = useCallback(async (email: string, password: string) => {
    const data = await apiJson<{ customer: Customer }>("/api/account/login", {
      method: "POST",
      body: JSON.stringify({ email, password }),
    });
    setCustomer(data.customer);
  }, []);

  const register = useCallback(
    async (regData: {
      email: string;
      password: string;
      first_name: string;
      last_name: string;
    }) => {
      const data = await apiJson<{ customer: Customer }>(
        "/api/account/register",
        {
          method: "POST",
          body: JSON.stringify(regData),
        },
      );
      setCustomer(data.customer);
    },
    [],
  );

  const logout = useCallback(async () => {
    await apiJson("/api/account/logout", { method: "POST" });
    setCustomer(null);
  }, []);

  const refreshCustomer = useCallback(async () => {
    try {
      const data = await apiJson<{ customer: Customer }>("/api/account/me");
      setCustomer(data.customer);
    } catch {
      setCustomer(null);
    }
  }, []);

  const value = useMemo<AuthState>(
    () => ({
      customer,
      isAuthenticated: !!customer,
      isLoading,
      login,
      register,
      logout,
      refreshCustomer,
    }),
    [customer, isLoading, login, register, logout, refreshCustomer],
  );

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

export function useAuth() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error("useAuth must be used within AuthProvider");
  return ctx;
}
