import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { User, Session } from '@supabase/supabase-js';
import { supabase } from '@/integrations/supabase/client';

interface Profile {
  id: string;
  user_id: string;
  display_name: string | null;
  avatar_url: string | null;
  bio: string | null;
  phone: string | null;
  role: string;
  email_verified: boolean;
  last_login: string | null;
  created_at: string;
  updated_at: string;
}

interface AuthContextType {
  user: User | null;
  session: Session | null;
  profile: Profile | null;
  loading: boolean;
  /** True when the current session is an anonymous (guest) one */
  isAnonymous: boolean;
  /** True when the current user has admin/super_admin role in user_roles (SSOT). */
  isAdmin: boolean;
  signUp: (email: string, password: string, displayName?: string) => Promise<{ error: any }>;
  signIn: (email: string, password: string) => Promise<{ error: any }>;
  /** Set session from SMS OTP verify response */
  setSessionFromSms: (accessToken: string, refreshToken: string) => Promise<void>;
  signOut: () => Promise<void>;
  updateProfile: (updates: Partial<Profile>) => Promise<{ error: any }>;
  refreshProfile: () => Promise<void>;
}

// Detect whether a Supabase user is an anonymous (guest) account
function detectAnonymous(u: User | null): boolean {
  if (!u) return false;
  // Supabase marks anonymous users with is_anonymous flag
  return Boolean((u as any).is_anonymous) || u.app_metadata?.provider === 'anonymous';
}

let anonymousSignInUnavailable = false;

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [session, setSession] = useState<Session | null>(null);
  const [profile, setProfile] = useState<Profile | null>(null);
  const [loading, setLoading] = useState(true);
  const [isAdmin, setIsAdmin] = useState(false);

  // Fetch admin status from user_roles (SSOT). Never derive from profile.role.
  const refreshAdminStatus = async (userId: string | null) => {
    if (!userId) { setIsAdmin(false); return; }
    try {
      const { data, error } = await supabase
        .from('user_roles')
        .select('role')
        .eq('user_id', userId)
        .in('role', ['admin', 'super_admin'])
        .limit(1)
        .maybeSingle();
      setIsAdmin(!error && !!data);
    } catch {
      setIsAdmin(false);
    }
  };

  useEffect(() => {
    console.log('AuthContext: useEffect 开始执行');
    let mounted = true;

    const ensureAnonymousSession = async () => {
      try {
        if (anonymousSignInUnavailable) return;
        const { data: { session: existing } } = await supabase.auth.getSession();
        if (existing) return;
        console.log('AuthContext: 无 session，自动创建匿名访客身份');
        const { error } = await supabase.auth.signInAnonymously();
        if (error) {
          if ((error as any).code === 'anonymous_provider_disabled' || error.message.includes('Anonymous sign-ins are disabled')) {
            anonymousSignInUnavailable = true;
          }
          console.warn('AuthContext: 匿名登录失败（请确认已在 Supabase 启用 Anonymous Sign-Ins）:', error.message);
        }
      } catch (e) {
        console.warn('AuthContext: ensureAnonymousSession 异常:', e);
      }
    };

    // Set up auth state listener
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (event, session) => {
        if (!mounted) return;

        console.log('AuthContext: onAuthStateChange 事件:', event, '会话存在:', !!session, '匿名:', detectAnonymous(session?.user ?? null));
        setSession(session);
        const nextUser = session?.user ?? null;
        // 切回浏览器时 Supabase 会 TOKEN_REFRESHED；保持 user 引用稳定，避免整棵子树卸载重挂
        setUser((prev) =>
          event === 'TOKEN_REFRESHED' && prev?.id === nextUser?.id ? prev : nextUser
        );

        if (session?.user) {
          // Only fetch profile for non-anonymous users (anonymous users have no profile row)
          if (!detectAnonymous(session.user) && event !== 'TOKEN_REFRESHED') {
            setTimeout(() => {
              if (mounted) {
                fetchUserProfile(session.user.id);
                refreshAdminStatus(session.user.id);
              }
            }, 0);
          } else if (detectAnonymous(session.user)) {
            setProfile(null);
            setIsAdmin(false);
          }
        } else {
          setProfile(null);
          setIsAdmin(false);
          // Lost session — re-create an anonymous one so chat keeps working
          setTimeout(() => { if (mounted) ensureAnonymousSession(); }, 0);
        }

        if (mounted) {
          setLoading(false);
        }
      }
    );

    // Bootstrap: check existing session, otherwise create anonymous
    (async () => {
      const { data: { session } } = await supabase.auth.getSession();
      if (!mounted) return;

      console.log('AuthContext: 启动获取到现有会话:', !!session);
      setSession(session);
      setUser(session?.user ?? null);

      if (session?.user && !detectAnonymous(session.user)) {
        setTimeout(() => { if (mounted) { fetchUserProfile(session.user.id); refreshAdminStatus(session.user.id); } }, 0);
      }

      if (!session) {
        await ensureAnonymousSession();
      }

      if (mounted) setLoading(false);
    })();

    return () => {
      mounted = false;
      subscription.unsubscribe();
    };
  }, []);

  const fetchUserProfile = async (userId: string) => {
    try {
      console.log('AuthContext: 开始获取用户资料 for user:', userId);
      const { data, error } = await supabase
        .from('profiles')
        .select('*')
        .eq('user_id', userId)
        .single();

      if (error) {
        console.error('AuthContext: 获取用户资料失败:', error);
        // Don't treat profile fetch errors as critical
        // Set profile to null and continue
        setProfile(null);
        return;
      }

      console.log('AuthContext: 用户资料获取成功:', data);
      setProfile(data);
    } catch (error) {
      console.error('AuthContext: 获取用户资料异常:', error);
      // Ensure we set profile to null on any error
      setProfile(null);
    }
  };

  const signUp = async (email: string, password: string, displayName?: string) => {
    const redirectUrl = `${window.location.origin}/`;
    
    const { error } = await supabase.auth.signUp({
      email,
      password,
      options: {
        emailRedirectTo: redirectUrl,
        data: displayName ? { display_name: displayName } : undefined
      }
    });
    
    return { error };
  };

  const signIn = async (email: string, password: string) => {
    const { error } = await supabase.auth.signInWithPassword({
      email,
      password
    });
    
    return { error };
  };

  const signOut = async () => {
    await supabase.auth.signOut();
    // After signing out, immediately create a fresh anonymous session
    // so the user can keep chatting as a guest.
    try {
      if (anonymousSignInUnavailable) return;
      await supabase.auth.signInAnonymously();
    } catch (e: any) {
      if (e?.code === 'anonymous_provider_disabled' || e?.message?.includes('Anonymous sign-ins are disabled')) {
        anonymousSignInUnavailable = true;
      }
      console.warn('AuthContext: 登出后重建匿名会话失败:', e);
    }
  };

  const updateProfile = async (updates: Partial<Profile>) => {
    if (!user) return { error: new Error('No user logged in') };

    const { error } = await supabase
      .from('profiles')
      .update(updates)
      .eq('user_id', user.id);

    if (!error && profile) {
      setProfile({ ...profile, ...updates });
    }

    return { error };
  };

  const refreshProfile = async () => {
    if (!user) return;
    await fetchUserProfile(user.id);
  };

  const setSessionFromSms = async (accessToken: string, refreshToken: string) => {
    // Capture the previous (possibly anonymous) user id BEFORE switching session
    const prevUserId = user?.id;
    const prevWasAnonymous = detectAnonymous(user);

    await supabase.auth.setSession({ access_token: accessToken, refresh_token: refreshToken });

    // If we were anonymous, migrate that data to the newly authenticated account
    if (prevWasAnonymous && prevUserId) {
      try {
        const { data: { user: newUser } } = await supabase.auth.getUser();
        if (newUser && newUser.id !== prevUserId) {
          console.log('AuthContext: 检测到匿名→正式升级，迁移历史数据', { from: prevUserId, to: newUser.id });
          const { data, error } = await supabase.rpc('merge_anonymous_user_data', {
            anon_user_id: prevUserId,
            target_user_id: newUser.id,
          });
          if (error) {
            console.warn('AuthContext: 匿名数据迁移失败:', error.message);
          } else {
            console.log('AuthContext: 匿名数据迁移成功:', data);
          }
        }
      } catch (e) {
        console.warn('AuthContext: 匿名数据迁移异常:', e);
      }
    }
  };

  const isAnonymous = detectAnonymous(user);

  return (
    <AuthContext.Provider
      value={{
        user,
        session,
        profile,
        loading,
        isAnonymous,
        isAdmin,
        signUp,
        signIn,
        signOut,
        updateProfile,
        refreshProfile,
        setSessionFromSms,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
}