import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { API_BASE_URL, TARGET_ENV, IS_WORDPRESS, ASSISTANT_ENABLED, ASSISTANT_BRAND_NAME, setAuthToken, clearAuthToken } from '../constants';

interface UserInfo {
  name: string;
  email: string;
  theme: 'system' | 'light' | 'dark';
  seo_consent: boolean | null;
}

interface AuthContextProps {
  isLoggedIn: boolean;
  userInfo: UserInfo | null;
  login: (email: string, password: string) => Promise<void>;
  logout: () => Promise<void>;
  signup: (name: string, email: string, password: string, verificationCode: string) => Promise<void>;
  updateEmail: (newEmail: string, currentPassword: string) => Promise<{ requiresVerification: boolean }>;
  updatePassword: (currentPassword: string, newPassword: string) => Promise<void>;
  setUserInfo: (info: UserInfo) => void;
  authError: string | null;
  setAuthError: (error: string | null) => void;
  requestVerification: (email: string, purpose: 'registration' | 'password_reset' | 'email_change') => Promise<void>;
  verifyCode: (email: string, code: string) => Promise<boolean>;
  resetPassword: (email: string, code: string, newPassword: string) => Promise<boolean>;
  // SEO Consent related properties
  seoConsent: boolean | null;
  hasDismissedBanner: boolean;
  setHasDismissedBanner: (value: boolean) => void;
  updateSeoConsent: (allowSeoUse: boolean) => Promise<void>;
}

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

interface AuthProviderProps {
  children: ReactNode;
}

export const AuthProvider = ({ children }: AuthProviderProps): JSX.Element => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
  const [authError, setAuthError] = useState<string | null>(null);
  const queryClient = useQueryClient();
  
  // SEO Consent related state
  const [seoConsent, setSeoConsent] = useState<boolean | null>(IS_WORDPRESS ? false : null);
  const [hasDismissedBanner, setHasDismissedBanner] = useState<boolean>(true);
  const isPluginAuthBlocked = TARGET_ENV === 'wordpress' && !ASSISTANT_ENABLED;

  // Update SEO consent preference
  const updateSeoConsent = async (allowSeoUse: boolean) => {
    if (IS_WORDPRESS) {
      setSeoConsent(false);
      if (isLoggedIn && userInfo) {
        setUserInfo({ ...userInfo, seo_consent: false });
      }
      try {
        document.cookie = `client_seo_consent=false; path=/; max-age=${365 * 24 * 60 * 60};`;
      } catch {}
      return;
    }

    try {
      // Update local state
      setSeoConsent(allowSeoUse);
      
      // Set client-side cookie directly
      document.cookie = `client_seo_consent=${allowSeoUse}; path=/; max-age=${365 * 24 * 60 * 60};`;
      
      // Send to server to set server-side cookie
      const response = await fetch(`${API_BASE_URL}/seo-consent`, {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ allow_seo_use: allowSeoUse }),
      });

      if (response.ok) {
        // For logged-in users, update userInfo
        if (isLoggedIn && userInfo) {
          setUserInfo({
            ...userInfo,
            seo_consent: allowSeoUse
          });
        }
      } else {
        console.error('Failed to update server-side SEO consent');
      }
    } catch (error) {
      console.error('Error updating SEO consent:', error);
    }
  };

  // Initialize client-side cookie and state
  useEffect(() => {
    if (IS_WORDPRESS) {
      setSeoConsent(false);
      setHasDismissedBanner(true);
      try {
        document.cookie = `client_seo_consent=false; path=/; max-age=${365 * 24 * 60 * 60};`;
      } catch {}
      return;
    }

    // Check for cookies
    const clientConsentCookie = document.cookie
      .split('; ')
      .find(row => row.startsWith('client_seo_consent='));
    const bannerDismissedCookie = document.cookie
      .split('; ')
      .find(row => row.startsWith('seo_banner_dismissed='));

    // --- Part 1: Determine Consent State ---
    let consentValue: boolean | null = null;
    let isNewUser = false;

    if (clientConsentCookie) {
      consentValue = clientConsentCookie.split('=')[1] === 'true';
    } else if (isLoggedIn && userInfo && userInfo.seo_consent !== null) {
      consentValue = userInfo.seo_consent;
      // Sync user profile setting to cookie for consistency
      document.cookie = `client_seo_consent=${consentValue}; path=/; max-age=${365 * 24 * 60 * 60};`;
    } else {
      // This is a new user/session. Default to opt-in.
      consentValue = true;
      isNewUser = true; // Flag to sync with backend
    }
    setSeoConsent(consentValue);

    // If it's a new user, set the default on the backend as well
    if (isNewUser) {
      const initializeBackendConsent = async (value: boolean) => {
        // Set client-side cookie immediately for non-logged-in users
        if (!isLoggedIn) {
          document.cookie = `client_seo_consent=${value}; path=/; max-age=${365 * 24 * 60 * 60};`;
        }
        try {
          await fetch(`${API_BASE_URL}/seo-consent`, {
            method: 'POST',
            credentials: 'include',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ allow_seo_use: value }),
          });
        } catch (error) {
          console.error('Failed to set default SEO consent on backend:', error);
        }
      };
      initializeBackendConsent(consentValue);
    }

    // --- Part 2: Determine Banner Visibility ---
    // The banner should only be shown once. If it has been dismissed, never show again.
    // Also, if a logged-in user has a preference, they've already "seen" it.
    if (bannerDismissedCookie) {
      setHasDismissedBanner(true);
    } else if (isLoggedIn && userInfo && userInfo.seo_consent !== null) {
      setHasDismissedBanner(true);
    } else {
      setHasDismissedBanner(false);
    }
  }, [isLoggedIn, userInfo]);
  
  // Check authentication status on mount
  useEffect(() => {
    const checkAuthStatus = async () => {
      if (isPluginAuthBlocked) {
        setIsLoggedIn(false);
        setUserInfo(null);
        return;
      }

      // console.log('checking auth status');
      let hasRetried = false;

      const fetchStatus = async () => {
        try {
          const response = await fetch(`${API_BASE_URL}/auth-status`, {
            method: 'GET',
            credentials: 'include',
          });

          if (response.status === 401 && !hasRetried) {
            hasRetried = true;
            console.log('Received 401. Retrying auth status check...');
            return await fetchStatus();
          }

          if (response.ok) {
            const data = await response.json();
            setIsLoggedIn(data.isLoggedIn);
          } else {
            setIsLoggedIn(false);
          }
        } catch (error) {
          console.error('Error checking auth status:', error);
          setIsLoggedIn(false);
        }
      };

      await fetchStatus();
    };

    checkAuthStatus();
  }, [isPluginAuthBlocked]);

  // Fetch user info when logged in
  const fetchUserInfo = useCallback(async () => {
    if (isPluginAuthBlocked) {
      setIsLoggedIn(false);
      setUserInfo(null);
      return;
    }

    if (!isLoggedIn) return;

    try {
      const response = await fetch(`${API_BASE_URL}/user-info`, {
        method: 'GET',
        credentials: 'include',
      });

      if (response.ok) {
        const data = await response.json();
        setUserInfo({
          name: data.name,
          email: data.email,
          theme: data.theme,
          seo_consent: data.seo_consent,
        });

        if (!IS_WORDPRESS) {
          // Update theme cookie
          document.cookie = `theme=${data.theme}; path=/;`;
        }
      } else {
        setIsLoggedIn(false);
        setUserInfo(null);
      }
    } catch (error) {
      console.error('Error fetching user info:', error);
      setIsLoggedIn(false);
      setUserInfo(null);
    }
  }, [isLoggedIn, isPluginAuthBlocked]);

  useEffect(() => {
    fetchUserInfo();
  }, [fetchUserInfo]);

  
  // Login function
  const login = useCallback(
    async (email: string, password: string) => {
      if (isPluginAuthBlocked) {
        const message = `Enable ${ASSISTANT_BRAND_NAME} in settings to use login and signup.`;
        setAuthError(message);
        throw new Error(message);
      }

      setAuthError(null);
      try {
        const response = await fetch(`${API_BASE_URL}/login`, {
          method: 'POST',
          credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ email, password }),
        });

        if (!response.ok) {
          const errorData = await response.json();
          setAuthError(errorData.detail || 'Failed to log in');
          throw new Error(errorData.detail || 'Failed to log in');
        }

        // Store bearer token in plugin mode to avoid 3rd-party cookie issues
        if (TARGET_ENV === 'wordpress') {
          try {
            const data = await response.json();
            if (data?.access_token) setAuthToken(data.access_token);
          } catch {}
        }

        queryClient.clear();
        window.location.reload();

      } catch (error) {
        console.error('Error during login:', error);
        throw error;
      }
    },
    [API_BASE_URL, queryClient, fetchUserInfo, isPluginAuthBlocked]
  );

  // Logout function
  const logout = useCallback(
    async () => {
      if (isPluginAuthBlocked) {
        clearAuthToken();
        setIsLoggedIn(false);
        setUserInfo(null);
        queryClient.clear();
        return;
      }

      setAuthError(null);
      try {
        const response = await fetch(`${API_BASE_URL}/logout`, {
          method: 'POST',
          credentials: 'include',
        });

        if (!IS_WORDPRESS) {
          // Remove the theme cookie
          document.cookie = `theme=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;`;
        }

        // Remove the client-side SEO consent cookie
        document.cookie = `client_seo_consent=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;`;

        if (!response.ok) {
          const errorData = await response.json();
          setAuthError(errorData.detail || 'Failed to log out');
          throw new Error(errorData.detail || 'Failed to log out');
        }

        // Clear stored bearer token in plugin mode
        if (TARGET_ENV === 'wordpress') {
          clearAuthToken();
        }

        queryClient.clear();
        window.location.reload();
      } catch (error) {
        console.error('Error during logout:', error);
        throw error;
      }
    },
    [API_BASE_URL, queryClient, isPluginAuthBlocked]
  );

  // Signup function
  const signup = useCallback(
    async (name: string, email: string, password: string, verificationCode: string) => {
      if (isPluginAuthBlocked) {
        const message = `Enable ${ASSISTANT_BRAND_NAME} in settings to use login and signup.`;
        setAuthError(message);
        throw new Error(message);
      }

      setAuthError(null);
      try {
        const response = await fetch(`${API_BASE_URL}/register`, {
          method: 'POST',
          credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            user: {
              name,
              email,
              password,
            },
            verification: {
              email,
              code: verificationCode
            }
          }),
        });

        if (!response.ok) {
          const errorData = await response.json();
          throw new Error(errorData.detail || 'Registration failed');
        }

        if (TARGET_ENV === 'wordpress') {
          try {
            const data = await response.json();
            if (data?.access_token) setAuthToken(data.access_token);
          } catch {}
        }
      
        queryClient.clear();
        window.location.reload();
      } catch (error) {
        const message = error instanceof Error ? error.message : 'Registration failed';
        setAuthError(message);
        throw error;
      }
    },
    [API_BASE_URL, queryClient, fetchUserInfo, isPluginAuthBlocked]
  );

  // Update Email
  const updateEmail = useCallback(
    async (newEmail: string, currentPassword: string) => {
      if (isPluginAuthBlocked) {
        const message = `Enable ${ASSISTANT_BRAND_NAME} in settings to use account features.`;
        setAuthError(message);
        throw new Error(message);
      }

      setAuthError(null);

      try {
        const response = await fetch(`${API_BASE_URL}/account/email`, {
          method: 'PUT',
          credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ new_email: newEmail, current_password: currentPassword }),
        });

        if (!response.ok) {
          const errorData = await response.json();
          setAuthError(errorData.detail || 'Failed to update email');
          throw new Error(errorData.detail || 'Failed to update email');
        }

        const data = await response.json();
        
        // Only update user info immediately if verification is not required
        if (!data.requires_verification) {
          await fetchUserInfo();
        }

        return { requiresVerification: data.requires_verification };
      } catch (error) {
        console.error('Error updating email:', error);
        throw error;
      }
    },
    [API_BASE_URL, fetchUserInfo, isPluginAuthBlocked]
  );

  // Update Password
  const updatePassword = useCallback(
    async (currentPassword: string, newPassword: string) => {
      if (isPluginAuthBlocked) {
        const message = `Enable ${ASSISTANT_BRAND_NAME} in settings to use account features.`;
        setAuthError(message);
        throw new Error(message);
      }

      setAuthError(null);

      try {
        const response = await fetch(`${API_BASE_URL}/account/password`, {
          method: 'PUT',
          credentials: 'include',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ current_password: currentPassword, new_password: newPassword }),
        });

        if (!response.ok) {
          const errorData = await response.json();
          setAuthError(errorData.detail || 'Failed to update password');
          throw new Error(errorData.detail || 'Failed to update password');
        }

        await fetchUserInfo();
      } catch (error) {
        console.error('Error updating password:', error);
        throw error;
      }
    },
    [API_BASE_URL, fetchUserInfo, isPluginAuthBlocked]
  );

  // Send verification code
  const requestVerification = useCallback(
    async (email: string, purpose: 'registration' | 'password_reset' | 'email_change') => {
      if (isPluginAuthBlocked) {
        const message = `Enable ${ASSISTANT_BRAND_NAME} in settings to use login and signup.`;
        setAuthError(message);
        throw new Error(message);
      }

      try {
        const response = await fetch(`${API_BASE_URL}/request-verification`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ 
            email: email.toLowerCase(),
            purpose: purpose 
          }),
        });

        if (!response.ok) {
          const errorData = await response.json();
          throw new Error(errorData.detail || 'Failed to send verification code');
        }
      } catch (error) {
        const message = error instanceof Error ? error.message : 'Failed to request verification';
        console.error('Error requesting verification:', message);
        throw new Error(message);
      }
    },
    [API_BASE_URL, isPluginAuthBlocked]
  );

  // Verify code
  const verifyCode = useCallback(async (email: string, code: string) => {
    if (isPluginAuthBlocked) {
      const message = `Enable ${ASSISTANT_BRAND_NAME} in settings to use account features.`;
      setAuthError(message);
      return false;
    }

    try {
      const response = await fetch(`${API_BASE_URL}/account/email/verify`, {
        method: 'PUT',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, code }),
      });

      const data = await response.json();

      if (!response.ok) {
        setAuthError(data.detail || 'Failed to verify code');
        throw new Error(data.detail || 'Failed to verify code');
      }

      await fetchUserInfo();
      return true;
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Verification failed';
      setAuthError(message);
      return false;
    }
  }, [API_BASE_URL, fetchUserInfo, isPluginAuthBlocked]);

  const resetPassword = useCallback(
    async (email: string, code: string, newPassword: string) => {
      if (isPluginAuthBlocked) {
        const message = `Enable ${ASSISTANT_BRAND_NAME} in settings to use login and signup.`;
        setAuthError(message);
        throw new Error(message);
      }

      setAuthError(null);
      try {
        const response = await fetch(`${API_BASE_URL}/reset-password`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            email,
            code,
            new_password: newPassword
          }),
        });

        if (!response.ok) {
          const errorData = await response.json();
          throw new Error(errorData.detail || 'Password reset failed');
        }

        return true;
      } catch (error) {
        const message = error instanceof Error ? error.message : 'Password reset failed';
        setAuthError(message);
        throw error;
      }
    },
    [API_BASE_URL, isPluginAuthBlocked]
  );

  const value: AuthContextProps = {
    isLoggedIn,
    userInfo,
    login,
    logout,
    setAuthError,
    signup,
    updateEmail,
    updatePassword,
    setUserInfo,
    authError,
    requestVerification,
    verifyCode,
    resetPassword,
    // SEO Consent related properties
    seoConsent,
    hasDismissedBanner,
    setHasDismissedBanner: (value: boolean) => {
      setHasDismissedBanner(value);
      if (value && !IS_WORDPRESS) {
        document.cookie = `seo_banner_dismissed=true; path=/; max-age=${365 * 24 * 60 * 60}; SameSite=Lax`;
      }
    },
    updateSeoConsent,
  };

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

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