import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import api from '@/lib/api';
import { showToast } from '@/components/ui/toast-utils';

export interface User {
  id: string;
  email: string;
  full_name: string;
  is_active: boolean;
  created_at: string;
}

export interface AuthTokens {
  access_token: string;
  refresh_token: string;
  token_type: string;
}

interface AuthContextType {
  user: User | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (email: string, password: string) => Promise<boolean>;
  logout: () => void;
  register: (email: string, password: string, fullName: string) => Promise<boolean>;
  requestPasswordReset: (email: string) => Promise<boolean>;
  resetPassword: (token: string, newPassword: string) => Promise<boolean>;
}

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

const TOKEN_KEY = 'auth_token';
const REFRESH_TOKEN_KEY = 'refresh_token';
const USER_KEY = 'auth_user';

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

  // Initialize auth state from localStorage
  useEffect(() => {
    const storedUser = localStorage.getItem(USER_KEY);
    const token = localStorage.getItem(TOKEN_KEY);
    
    if (storedUser && token) {
      try {
        setUser(JSON.parse(storedUser));
        // Set default authorization header
        api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
      } catch {
        // Invalid stored data, clear it
        localStorage.removeItem(USER_KEY);
        localStorage.removeItem(TOKEN_KEY);
        localStorage.removeItem(REFRESH_TOKEN_KEY);
      }
    }
    setIsLoading(false);
  }, []);

  // Setup axios interceptor to add Authorization header
  useEffect(() => {
    const interceptor = api.interceptors.request.use(
      (config) => {
        const token = localStorage.getItem(TOKEN_KEY);
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error) => Promise.reject(error)
    );

    return () => {
      api.interceptors.request.eject(interceptor);
    };
  }, []);

  const login = useCallback(async (email: string, password: string): Promise<boolean> => {
    try {
      const response = await api.post('/auth/login', { email, password });
      const { access_token, refresh_token, token_type } = response.data;
      
      // Store tokens
      localStorage.setItem(TOKEN_KEY, access_token);
      localStorage.setItem(REFRESH_TOKEN_KEY, refresh_token);
      
      // Set authorization header
      api.defaults.headers.common['Authorization'] = `${token_type} ${access_token}`;
      
      // Fetch user info
      const userResponse = await api.get('/auth/me');
      const userData = userResponse.data;
      
      setUser(userData);
      localStorage.setItem(USER_KEY, JSON.stringify(userData));
      
      showToast({ 
        title: 'Welcome back!', 
        description: `Logged in as ${userData.email}` 
      });
      
      return true;
    } catch (error: any) {
      const message = error.response?.data?.detail || 'Invalid credentials';
      showToast({ 
        title: 'Login failed', 
        description: message,
        variant: 'destructive'
      });
      return false;
    }
  }, []);

  const register = useCallback(async (email: string, password: string, fullName: string): Promise<boolean> => {
    try {
      const response = await api.post('/auth/register', { 
        email, 
        password, 
        full_name: fullName 
      });
      const { access_token, refresh_token, token_type, user: userData } = response.data;
      
      // Store tokens
      localStorage.setItem(TOKEN_KEY, access_token);
      localStorage.setItem(REFRESH_TOKEN_KEY, refresh_token);
      
      // Set authorization header
      api.defaults.headers.common['Authorization'] = `${token_type} ${access_token}`;
      
      setUser(userData);
      localStorage.setItem(USER_KEY, JSON.stringify(userData));
      
      showToast({ 
        title: 'Account created!', 
        description: 'Welcome to mockupAWS' 
      });
      
      return true;
    } catch (error: any) {
      const message = error.response?.data?.detail || 'Registration failed';
      showToast({ 
        title: 'Registration failed', 
        description: message,
        variant: 'destructive'
      });
      return false;
    }
  }, []);

  const logout = useCallback(() => {
    setUser(null);
    localStorage.removeItem(TOKEN_KEY);
    localStorage.removeItem(REFRESH_TOKEN_KEY);
    localStorage.removeItem(USER_KEY);
    delete api.defaults.headers.common['Authorization'];

    showToast({
      title: 'Logged out',
      description: 'See you soon!'
    });
  }, []);

  const requestPasswordReset = useCallback(async (email: string): Promise<boolean> => {
    try {
      await api.post('/auth/reset-password-request', { email });

      showToast({
        title: 'Reset email sent',
        description: 'Check your email for password reset instructions'
      });

      return true;
    } catch (error: any) {
      const message = error.response?.data?.detail || 'Failed to send reset email';
      showToast({
        title: 'Request failed',
        description: message,
        variant: 'destructive'
      });
      return false;
    }
  }, []);

  const resetPassword = useCallback(async (token: string, newPassword: string): Promise<boolean> => {
    try {
      await api.post('/auth/reset-password', {
        token,
        new_password: newPassword
      });

      showToast({
        title: 'Password reset successful',
        description: 'You can now log in with your new password'
      });

      return true;
    } catch (error: any) {
      const message = error.response?.data?.detail || 'Failed to reset password';
      showToast({
        title: 'Reset failed',
        description: message,
        variant: 'destructive'
      });
      return false;
    }
  }, []);

  return (
    <AuthContext.Provider value={{
      user,
      isAuthenticated: !!user,
      isLoading,
      login,
      logout,
      register,
      requestPasswordReset,
      resetPassword,
    }}>
      {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;
}