import React, {
  createContext,
  useContext,
  useState,
  useEffect,
  ReactNode,
} from 'react';
import { User } from '../types';
import { databaseService } from '../services/database';
import { authService } from '../services/auth/auth.service';
import { tokenStorage } from '../utils/token';

const SESSION_KEY = 'medication_app_session';

interface UserContextType {
  user: User | null;
  isLoading: boolean;
  login: (email: string, password: string) => Promise<boolean>;
  register: (
    email: string,
    password: string,
    username?: string
  ) => Promise<boolean>;
  loginWithOAuth: (
    provider: 'google' | 'github',
    userData: { email: string; username: string; avatar?: string }
  ) => Promise<boolean>;
  changePassword: (
    currentPassword: string,
    newPassword: string
  ) => Promise<boolean>;
  logout: () => void;
  updateUser: (
    updatedUser: Omit<User, '_rev'> & { _rev: string }
  ) => Promise<void>;
}

const UserContext = createContext<UserContextType | undefined>(undefined);

export const UserProvider: React.FC<{ children: ReactNode }> = ({
  children,
}) => {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    try {
      const sessionUser = localStorage.getItem(SESSION_KEY);
      if (sessionUser) {
        setUser(JSON.parse(sessionUser));
      }
    } catch {
      // silent fail
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (user) {
      localStorage.setItem(SESSION_KEY, JSON.stringify(user));
    } else {
      localStorage.removeItem(SESSION_KEY);
    }
  }, [user]);

  const login = async (email: string, password: string): Promise<boolean> => {
    try {
      // Use auth service for password-based login
      const result = await authService.login({ email, password });

      console.warn('Login result received:', result);
      console.warn('User from login:', result.user);
      console.warn('User _id:', result.user._id);

      // Update last login time
      const updatedUser = { ...result.user, lastLoginAt: new Date() };
      await databaseService.updateUser(updatedUser);

      console.warn('Updated user with last login:', updatedUser);

      tokenStorage.save({
        accessToken: result.accessToken,
        refreshToken: result.refreshToken,
      });
      // Set the user from the login result
      setUser(updatedUser);

      console.warn('User set in context');
      return true;
    } catch (error) {
      console.error('Login error:', error);
      return false;
    }
  };

  const register = async (
    email: string,
    password: string,
    username?: string
  ): Promise<boolean> => {
    try {
      await authService.register(email, password, username);
      // Don't auto-login after registration, require email verification
      return true;
    } catch (error) {
      console.error('Registration error:', error);
      return false;
    }
  };

  const loginWithOAuth = async (
    provider: 'google' | 'github',
    userData: { email: string; username: string; avatar?: string }
  ): Promise<boolean> => {
    try {
      const result = await authService.loginWithOAuth(provider, userData);

      console.warn('OAuth login result received:', result);
      console.warn('OAuth user:', result.user);
      console.warn('OAuth user _id:', result.user._id);

      // Update last login time
      const updatedUser = { ...result.user, lastLoginAt: new Date() };
      await databaseService.updateUser(updatedUser);

      console.warn('Updated OAuth user with last login:', updatedUser);

      tokenStorage.save({
        accessToken: result.accessToken,
        refreshToken: result.refreshToken,
      });
      setUser(updatedUser);

      console.warn('OAuth user set in context');
      return true;
    } catch (error) {
      console.error('OAuth login error:', error);
      return false;
    }
  };

  const changePassword = async (
    currentPassword: string,
    newPassword: string
  ): Promise<boolean> => {
    try {
      if (!user) {
        throw new Error('No user logged in');
      }

      await authService.changePassword(user._id, currentPassword, newPassword);
      return true;
    } catch (error) {
      console.error('Password change error:', error);
      return false;
    }
  };

  const logout = () => {
    tokenStorage.clear();
    setUser(null);
  };

  const updateUser = async (updatedUser: User) => {
    try {
      const savedUser = await databaseService.updateUser(updatedUser);
      setUser(savedUser);
    } catch (error) {
      console.error('Failed to update user', error);
      // Optionally revert state or show error
    }
  };

  if (isLoading) {
    return (
      <div className='min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900'>
        <PillIcon className='w-12 h-12 text-indigo-500 animate-spin' />
      </div>
    );
  }

  return (
    <UserContext.Provider
      value={{
        user,
        isLoading: false,
        login,
        register,
        loginWithOAuth,
        changePassword,
        logout,
        updateUser,
      }}
    >
      {children}
    </UserContext.Provider>
  );
};

export const useUser = (): UserContextType => {
  const context = useContext(UserContext);
  if (context === undefined) {
    throw new Error('useUser must be used within a UserProvider');
  }
  return context;
};

// Dummy icon for loading screen
const PillIcon: React.FC<React.SVGProps<SVGSVGElement>> = props => (
  <svg
    xmlns='http://www.w3.org/2000/svg'
    width='24'
    height='24'
    viewBox='0 0 24 24'
    fill='none'
    stroke='currentColor'
    strokeWidth='2'
    strokeLinecap='round'
    strokeLinejoin='round'
    {...props}
  >
    <path d='m10.5 20.5 10-10a4.95 4.95 0 1 0-7-7l-10 10a4.95 4.95 0 1 0 7 7Z' />
    <path d='m8.5 8.5 7 7' />
  </svg>
);
