"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import {
  clearSession,
  getPublicProfile,
  readSession,
  registerAccount,
  setSession,
  updateDisplayName,
  verifyCredentials,
  type PublicCredentials,
} from "@/lib/cyberluxAccount";

export type AccountContextValue = {
  user: PublicCredentials | null;
  hydrated: boolean;
  signIn: (username: string, password: string) => Promise<{ ok: true } | { ok: false; error: string }>;
  signUp: (
    username: string,
    password: string,
    displayName?: string,
  ) => Promise<{ ok: true } | { ok: false; error: string }>;
  signOut: () => void;
  refreshProfile: () => void;
  saveDisplayName: (displayName: string) => { ok: true } | { ok: false; error: string };
};

const AccountContext = createContext<AccountContextValue | undefined>(undefined);

export function useAccount(): AccountContextValue {
  const ctx = useContext(AccountContext);
  if (!ctx) {
    throw new Error("useAccount must be used within AccountProvider");
  }
  return ctx;
}

export function AccountProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<PublicCredentials | null>(null);
  const [hydrated, setHydrated] = useState(false);

  const refreshProfile = useCallback(() => {
    const s = readSession();
    if (!s) {
      setUser(null);
      return;
    }
    const p = getPublicProfile(s.username);
    setUser(p);
  }, []);

  useEffect(() => {
    refreshProfile();
    setHydrated(true);
  }, [refreshProfile]);

  const signIn = useCallback(
    async (username: string, password: string) => {
      const res = await verifyCredentials(username, password);
      if (!res.ok) return res;
      setSession(res.profile.username);
      setUser(res.profile);
      return { ok: true as const };
    },
    [],
  );

  const signUp = useCallback(async (username: string, password: string, displayName?: string) => {
    const reg = await registerAccount(username, password, displayName);
    if (!reg.ok) return reg;
    const res = await verifyCredentials(username, password);
    if (!res.ok) return { ok: false, error: "Account created but sign-in failed — try again." };
    setSession(res.profile.username);
    setUser(res.profile);
    return { ok: true as const };
  }, []);

  const signOut = useCallback(() => {
    clearSession();
    setUser(null);
  }, []);

  const saveDisplayName = useCallback(
    (displayName: string): { ok: true } | { ok: false; error: string } => {
      if (!user) return { ok: false, error: "Not signed in." };
      const dn = displayName.trim();
      if (dn.length < 2) return { ok: false, error: "Display name needs at least 2 characters." };
      if (!updateDisplayName(user.username, dn)) return { ok: false, error: "Could not update profile." };
      setUser({ ...user, displayName: dn });
      return { ok: true };
    },
    [user],
  );

  const value = useMemo(
    () => ({
      user,
      hydrated,
      signIn,
      signUp,
      signOut,
      refreshProfile,
      saveDisplayName,
    }),
    [user, hydrated, signIn, signUp, signOut, refreshProfile, saveDisplayName],
  );

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