/**
 * Multi-Tenant Authentication Context
 * Handles authentication for different tenants and providers
 */

import React, { createContext, useContext, useReducer, useEffect } from 'react';
import api from '../services/api';

const MultiTenantAuthContext = createContext();

const authReducer = (state, action) => {
  switch (action.type) {
    case 'SET_LOADING':
      return { ...state, loading: action.payload };
    case 'SET_TENANT':
      return { ...state, tenant: action.payload };
    case 'SET_AUTH_CONFIG':
      return { ...state, authConfig: action.payload };
    case 'LOGIN_START':
      return { ...state, loading: true, error: null };
    case 'LOGIN_SUCCESS':
      return { 
        ...state, 
        user: action.payload.user, 
        token: action.payload.token,
        tenant: action.payload.tenant,
        isAuthenticated: true, 
        loading: false, 
        error: null 
      };
    case 'LOGIN_FAILURE':
      return { ...state, loading: false, error: action.payload, isAuthenticated: false };
    case 'LOGOUT':
      return { ...state, user: null, token: null, isAuthenticated: false, loading: false };
    case 'SET_ERROR':
      return { ...state, error: action.payload, loading: false };
    default:
      return state;
  }
};

const initialState = {
  user: null,
  token: localStorage.getItem('token'),
  tenant: null,
  authConfig: null,
  isAuthenticated: false,
  loading: true,
  error: null
};

export const MultiTenantAuthProvider = ({ children }) => {
  const [state, dispatch] = useReducer(authReducer, initialState);

  // Determine tenant from URL or storage
  const determineTenant = () => {
    // Method 1: Subdomain
    const hostname = window.location.hostname;
    const subdomain = hostname.split('.')[0];
    if (subdomain && subdomain !== 'www' && subdomain !== 'localhost' && !hostname.includes('127.0.0.1')) {
      return subdomain;
    }

    // Method 2: URL parameter
    const urlParams = new URLSearchParams(window.location.search);
    if (urlParams.get('tenant')) {
      return urlParams.get('tenant');
    }

    // Method 3: Local storage
    const storedTenant = localStorage.getItem('tenant');
    if (storedTenant) {
      return storedTenant;
    }

    // Default tenant
    return 'default';
  };

  // Initialize authentication
  useEffect(() => {
    const initAuth = async () => {
      try {
        const tenantId = determineTenant();
        dispatch({ type: 'SET_TENANT', payload: tenantId });
        localStorage.setItem('tenant', tenantId);

        // Get tenant auth configuration
        const authConfigResponse = await api.get(`/auth/config/${tenantId}`);
        dispatch({ type: 'SET_AUTH_CONFIG', payload: authConfigResponse.data.data });

        // Check if user is already authenticated
        const token = localStorage.getItem('token');
        if (token) {
          // Validate token with current tenant context
          const profileResponse = await api.get('/users/profile');
          dispatch({ 
            type: 'LOGIN_SUCCESS', 
            payload: { 
              user: profileResponse.data.data, 
              token: token,
              tenant: tenantId
            } 
          });
        } else {
          dispatch({ type: 'SET_LOADING', payload: false });
        }
      } catch (error) {
        console.error('Auth initialization error:', error);
        localStorage.removeItem('token');
        dispatch({ type: 'SET_LOADING', payload: false });
      }
    };

    initAuth();
  }, []);

  // Handle URL token (from SSO redirects)
  useEffect(() => {
    const urlParams = new URLSearchParams(window.location.search);
    const urlToken = urlParams.get('token');
    const urlTenant = urlParams.get('tenant');
    
    if (urlToken && urlTenant) {
      localStorage.setItem('token', urlToken);
      localStorage.setItem('tenant', urlTenant);
      
      // Clean URL
      window.history.replaceState({}, document.title, window.location.pathname);
      
      // Reload to reinitialize with new token
      window.location.reload();
    }
  }, []);

  // Login function
  const login = async (credentials) => {
    try {
      dispatch({ type: 'LOGIN_START' });
      
      const tenantId = state.tenant || determineTenant();
      
      // For local authentication, use existing login endpoint
      if (state.authConfig?.provider === 'local' || state.authConfig?.provider === 'ldap') {
        const response = await api.post('/auth/login', {
          ...credentials,
          tenant: tenantId
        });
        
        const { user, token } = response.data.data;
        localStorage.setItem('token', token);
        localStorage.setItem('tenant', tenantId);
        
        dispatch({ 
          type: 'LOGIN_SUCCESS', 
          payload: { user, token, tenant: tenantId } 
        });
        
        return { success: true };
      } else {
        // For SSO providers, redirect to SSO endpoint
        const ssoUrl = getSSOLoginUrl(state.authConfig, tenantId);
        window.location.href = ssoUrl;
        return { success: true, redirect: true };
      }
    } catch (error) {
      const errorMessage = error.response?.data?.message || 'Login failed';
      dispatch({ type: 'LOGIN_FAILURE', payload: errorMessage });
      return { success: false, error: errorMessage };
    }
  };

  // SSO Login
  const loginWithSSO = () => {
    const tenantId = state.tenant || determineTenant();
    const ssoUrl = getSSOLoginUrl(state.authConfig, tenantId);
    window.location.href = ssoUrl;
  };

  // Get SSO login URL
  const getSSOLoginUrl = (authConfig, tenantId) => {
    const returnUrl = encodeURIComponent(window.location.pathname + window.location.search);
    
    switch (authConfig?.provider) {
      case 'saml':
        return `/auth/saml/${tenantId}/login?returnUrl=${returnUrl}`;
      case 'oauth':
        return `/auth/oauth/${tenantId}/login?returnUrl=${returnUrl}`;
      default:
        return `/login?tenant=${tenantId}`;
    }
  };

  // Logout
  const logout = async () => {
    try {
      const tenantId = state.tenant;
      
      // Call logout endpoint
      const response = await api.post('/auth/logout');
      
      // Clear local storage
      localStorage.removeItem('token');
      localStorage.removeItem('tenant');
      
      dispatch({ type: 'LOGOUT' });
      
      // Handle provider-specific logout
      if (response.data.logout_url) {
        window.location.href = response.data.logout_url;
      } else {
        window.location.href = `/login?tenant=${tenantId}`;
      }
    } catch (error) {
      console.error('Logout error:', error);
      // Force logout even if API call fails
      localStorage.removeItem('token');
      localStorage.removeItem('tenant');
      dispatch({ type: 'LOGOUT' });
      window.location.href = '/login';
    }
  };

  // Switch tenant
  const switchTenant = (newTenantId) => {
    localStorage.setItem('tenant', newTenantId);
    localStorage.removeItem('token'); // Clear token when switching tenants
    window.location.href = `/login?tenant=${newTenantId}`;
  };

  const value = {
    ...state,
    login,
    logout,
    loginWithSSO,
    switchTenant,
    getSSOLoginUrl
  };

  return (
    <MultiTenantAuthContext.Provider value={value}>
      {children}
    </MultiTenantAuthContext.Provider>
  );
};

export const useMultiTenantAuth = () => {
  const context = useContext(MultiTenantAuthContext);
  if (!context) {
    throw new Error('useMultiTenantAuth must be used within a MultiTenantAuthProvider');
  }
  return context;
};

export default MultiTenantAuthContext;
