"use client";
import { useState, useEffect, useCallback, createContext, useContext } from "react";
import { api } from "@/lib/api";
import {
  hasNostrExtension,
  getPublicKey,
  signEvent,
  createAuthEvent,
  fetchNostrProfile,
  createBunkerSigner,
  type BunkerSignerInterface,
  type NostrProfile,
} from "@/lib/nostr";

export interface User {
  pubkey: string;
  role: string;
  username?: string;
  name?: string;
  picture?: string;
  about?: string;
  nip05?: string;
  displayName?: string;
}

interface AuthContextType {
  user: User | null;
  loading: boolean;
  login: () => Promise<User>;
  loginWithBunker: (input: string) => Promise<User>;
  loginWithConnectedSigner: (signer: BunkerSignerInterface) => Promise<User>;
  logout: () => void;
  isAdmin: boolean;
  isModerator: boolean;
}

export const AuthContext = createContext<AuthContextType>({
  user: null,
  loading: true,
  login: async () => ({ pubkey: "", role: "USER" }),
  loginWithBunker: async () => ({ pubkey: "", role: "USER" }),
  loginWithConnectedSigner: async () => ({ pubkey: "", role: "USER" }),
  logout: () => {},
  isAdmin: false,
  isModerator: false,
});

export function useAuth() {
  return useContext(AuthContext);
}

export function useAuthProvider(): AuthContextType {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const stored = localStorage.getItem("bbe_user");
    const token = localStorage.getItem("bbe_token");
    if (stored && token) {
      try {
        setUser(JSON.parse(stored));
      } catch {
        localStorage.removeItem("bbe_user");
        localStorage.removeItem("bbe_token");
      }
    }
    setLoading(false);
  }, []);

  const completeAuth = useCallback(
    async (
      getPubKey: () => Promise<string>,
      sign: (event: any) => Promise<any>
    ): Promise<User> => {
      const pubkey = await getPubKey();
      const { challenge } = await api.getChallenge(pubkey);
      const event = createAuthEvent(pubkey, challenge);
      const signedEvent = await sign(event);
      const { token, user: userData } = await api.verify(pubkey, signedEvent);

      let profile: NostrProfile = {};
      try {
        profile = await fetchNostrProfile(pubkey);
      } catch {
        // Profile fetch is best-effort
      }

      const fullUser: User = {
        ...userData,
        name: profile.name,
        displayName: profile.displayName,
        picture: profile.picture,
        about: profile.about,
        nip05: profile.nip05,
        username: userData.username,
      };

      localStorage.setItem("bbe_token", token);
      localStorage.setItem("bbe_user", JSON.stringify(fullUser));
      setUser(fullUser);
      return fullUser;
    },
    []
  );

  const login = useCallback(async (): Promise<User> => {
    if (!hasNostrExtension()) {
      throw new Error("Please install a Nostr extension (e.g., Alby, nos2x)");
    }
    return completeAuth(getPublicKey, signEvent);
  }, [completeAuth]);

  const loginWithConnectedSigner = useCallback(
    async (signer: BunkerSignerInterface): Promise<User> => {
      return completeAuth(
        () => signer.getPublicKey(),
        (event) => signer.signEvent(event)
      );
    },
    [completeAuth]
  );

  const loginWithBunker = useCallback(
    async (input: string): Promise<User> => {
      const { signer } = await createBunkerSigner(input);
      try {
        return await loginWithConnectedSigner(signer);
      } finally {
        await signer.close().catch(() => {});
      }
    },
    [loginWithConnectedSigner]
  );

  const logout = useCallback(() => {
    localStorage.removeItem("bbe_token");
    localStorage.removeItem("bbe_user");
    setUser(null);
  }, []);

  return {
    user,
    loading,
    login,
    loginWithBunker,
    loginWithConnectedSigner,
    logout,
    isAdmin: user?.role === "ADMIN",
    isModerator: user?.role === "MODERATOR" || user?.role === "ADMIN",
  };
}
