/**
 * Tanflow Authentication Service
 * Handles OAuth flow with Tanflow IAM Suite
 */

import { TokenManager } from '../utils/tokenManager';
import axios from 'axios';

const TANFLOW_BASE_URL = import.meta.env.VITE_TANFLOW_BASE_URL || '';
const TANFLOW_CLIENT_ID = import.meta.env.VITE_TANFLOW_CLIENT_ID || '';
const TANFLOW_REDIRECT_URI = `${window.location.origin}/login/callback`;

/**
 * Initiate Tanflow SSO login
 * Redirects user to Tanflow authorization endpoint
 */
export function initiateTanflowLogin(): void {
  // Check if we're coming from a logout - if so, add prompt=login to force re-authentication
  const urlParams = new URLSearchParams(window.location.search);
  const isAfterLogout = urlParams.has('logout') || urlParams.has('tanflow_logged_out');

  // Clear any previous logout flags before starting new login
  if (isAfterLogout) {
    sessionStorage.removeItem('tanflow_logged_out');
    sessionStorage.removeItem('__logout_in_progress__');
    sessionStorage.removeItem('__force_logout__');
  }

  const state = Math.random().toString(36).substring(7);
  // Store provider type and state to identify Tanflow callback
  sessionStorage.setItem('auth_provider', 'tanflow');
  sessionStorage.setItem('tanflow_auth_state', state);

  let authUrl = `${TANFLOW_BASE_URL}/protocol/openid-connect/auth?` +
    `client_id=${TANFLOW_CLIENT_ID}&` +
    `response_type=code&` +
    `scope=openid&` +
    `redirect_uri=${encodeURIComponent(TANFLOW_REDIRECT_URI)}&` +
    `state=${state}`;

  // Add prompt=login if coming from logout to force re-authentication
  // This ensures Tanflow requires login even if a session still exists
  if (isAfterLogout) {
    authUrl += `&prompt=login`;
  }

  window.location.href = authUrl;
}

/**
 * Exchange authorization code for tokens via backend
 * Backend handles the token exchange securely with client secret
 */
export async function exchangeTanflowCodeForTokens(
  code: string,
  state: string
): Promise<{
  accessToken: string;
  refreshToken: string;
  idToken: string;
  user: any;
}> {
  const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '';

  try {
    const response = await axios.post(
      `${API_BASE_URL}/auth/tanflow/token-exchange`,
      {
        code,
        redirectUri: TANFLOW_REDIRECT_URI,
        state,
      },
      {
        withCredentials: true,
        headers: {
          'Content-Type': 'application/json',
        },
      }
    );

    const data = response.data?.data || response.data;

    // Store tokens
    if (data.accessToken) {
      TokenManager.setAccessToken(data.accessToken);
    }
    if (data.refreshToken) {
      TokenManager.setRefreshToken(data.refreshToken);
    }
    if (data.idToken) {
      TokenManager.setIdToken(data.idToken);
    }
    if (data.user) {
      TokenManager.setUserData(data.user);
    }

    return data;
  } catch (error: any) {
    console.error('❌ Tanflow token exchange failed:', {
      message: error.message,
      response: error.response?.data,
      status: error.response?.status,
    });
    throw error;
  }
}

/**
 * Refresh access token using refresh token
 */
export async function refreshTanflowToken(): Promise<string> {
  const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '';
  const refreshToken = TokenManager.getRefreshToken();

  if (!refreshToken) {
    throw new Error('No refresh token available');
  }

  try {
    const response = await axios.post(
      `${API_BASE_URL}/auth/tanflow/refresh`,
      { refreshToken },
      {
        withCredentials: true,
        headers: {
          'Content-Type': 'application/json',
        },
      }
    );

    const data = response.data?.data || response.data;
    const accessToken = data.accessToken;

    if (accessToken) {
      TokenManager.setAccessToken(accessToken);
      return accessToken;
    }

    throw new Error('Failed to refresh token');
  } catch (error: any) {
    console.error('❌ Tanflow token refresh failed:', error);
    throw error;
  }
}

/**
 * Logout from Tanflow
 * Uses id_token for logout and redirects back to app
 * Note: This should be called AFTER backend logout API is called and tokens are cleared
 * DO NOT clear tokens here - they should already be cleared by AuthContext
 */
export function tanflowLogout(idToken: string): void {
  if (!idToken) {
    console.warn('🚪 No id_token available for Tanflow logout, redirecting to home');
    // Fallback: redirect to home with logout flags (similar to OKTA approach)
    const homeUrl = `${window.location.origin}/?tanflow_logged_out=true&logout=${Date.now()}`;
    window.location.replace(homeUrl);
    return;
  }

  // Construct logout URL - ensure all parameters are properly encoded
  const logoutUrl = new URL(`${TANFLOW_BASE_URL}/protocol/openid-connect/logout`);
  logoutUrl.searchParams.set('client_id', TANFLOW_CLIENT_ID);
  logoutUrl.searchParams.set('id_token_hint', idToken);
  
  // Use the exact whitelisted login callback URI without query params to avoid mismatch errors
  const redirectUri = `${window.location.origin}/login/callback`;
  
  // Persist logout flag in sessionStorage before redirecting 
  // This allows AuthContext to detect the return from logout without query params 
  sessionStorage.setItem('__logout_type__', 'tanflow');
  
  logoutUrl.searchParams.set('post_logout_redirect_uri', redirectUri);

  const finalLogoutUrl = logoutUrl.toString();


  // DO NOT clear auth_provider here - we need it to detect Tanflow callback
  // The logout flags should already be set by AuthContext
  // Just ensure they're there
  sessionStorage.setItem('__logout_in_progress__', 'true');
  sessionStorage.setItem('__force_logout__', 'true');
  // Don't set tanflow_logged_out here - it will be set when Tanflow redirects back

  // Redirect to Tanflow logout endpoint
  // Tanflow will clear the session and redirect back to post_logout_redirect_uri
  // The redirect will include tanflow_logged_out=true in the query params
  window.location.href = finalLogoutUrl;
}

