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

import type { UserRecord } from '@/types/collections';
import { hydratePocketBaseAuth, isAuthenticated, pb } from '@/services/pocketbase';

type AuthContextValue = {
  user: UserRecord | null;
  loading: boolean;
  login: (email: string, password: string) => Promise<void>;
  register: (params: { email: string; password: string; name: string }) => Promise<void>;
  logout: () => void;
};

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

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<UserRecord | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    void (async () => {
      await hydratePocketBaseAuth();
      if (cancelled) return;
      setUser((pb.authStore.record as UserRecord | null) ?? null);
      setLoading(false);
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  useEffect(() => {
    const unsub = pb.authStore.onChange(() => {
      setUser((pb.authStore.record as UserRecord | null) ?? null);
    });
    return () => unsub();
  }, []);

  const login = useCallback(async (email: string, password: string) => {
    await pb.collection('users').authWithPassword(email.trim(), password);
    setUser((pb.authStore.record as UserRecord | null) ?? null);
  }, []);

  const register = useCallback(async (params: { email: string; password: string; name: string }) => {
    await pb.collection('users').create({
      email: params.email.trim(),
      password: params.password,
      passwordConfirm: params.password,
      name: params.name.trim(),
      emailVisibility: true,
    });
    await pb.collection('users').authWithPassword(params.email.trim(), params.password);
    setUser((pb.authStore.record as UserRecord | null) ?? null);
  }, []);

  const logout = useCallback(() => {
    pb.authStore.clear();
    setUser(null);
  }, []);

  const value = useMemo(
    () => ({
      user,
      loading,
      login,
      register,
      logout,
    }),
    [user, loading, login, register, logout],
  );

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

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

export { isAuthenticated };
