/**
 * Example: Official Account Authentication with PKCE
 * Demonstrates how to use the updated createOAAuthUrl method with PKCE support
 */

import { ZaloSDK } from '../src';

// Initialize SDK
const sdk = new ZaloSDK({
  appId: 'your_app_id',
  appSecret: 'your_app_secret',
});

// Example 1: Basic OA Auth without PKCE
async function basicOAAuth() {
  console.log('=== Basic OA Auth (without PKCE) ===');
  
  const redirectUri = 'https://your-app.com/callback';
  
  // Create auth URL - state will be auto-generated with 'zalo_oa_' prefix
  const authResult = sdk.auth.createOAAuthUrl(redirectUri);
  
  console.log('Authorization URL:', authResult.url);
  console.log('Generated State:', authResult.state);
  
  // You can also provide custom state
  const customAuthResult = sdk.auth.createOAAuthUrl(redirectUri, 'my_custom_state');
  console.log('Custom State URL:', customAuthResult.url);
  console.log('Custom State:', customAuthResult.state);
}

// Example 2: OA Auth with PKCE for enhanced security (Manual PKCE)
async function oaAuthWithPKCE() {
  console.log('\n=== OA Auth with Manual PKCE ===');

  const redirectUri = 'https://your-app.com/callback';

  // Step 1: Generate PKCE configuration
  const pkce = sdk.auth.generatePKCE();
  console.log('Generated PKCE:');
  console.log('- Code Verifier:', pkce.code_verifier);
  console.log('- Code Challenge:', pkce.code_challenge);
  console.log('- Challenge Method:', pkce.code_challenge_method);

  // Step 2: Create auth URL with manual PKCE
  const authResult = sdk.auth.createOAAuthUrl(redirectUri, undefined, pkce, true);

  console.log('\nAuthorization URL with PKCE:', authResult.url);
  console.log('Generated State:', authResult.state);
  console.log('Used PKCE:', authResult.pkce);

  // IMPORTANT: Store the code_verifier and state for later use
  // You'll need these when exchanging the authorization code for access token
  console.log('\n⚠️  IMPORTANT: Store these values for token exchange:');
  console.log('- Code Verifier:', pkce.code_verifier);
  console.log('- State:', authResult.state);

  return { pkce, state: authResult.state };
}

// Example 2b: OA Auth with Auto-Generated PKCE
async function oaAuthWithAutoPKCE() {
  console.log('\n=== OA Auth with Auto-Generated PKCE ===');

  const redirectUri = 'https://your-app.com/callback';

  // Create auth URL with auto-generated PKCE (pkce=undefined, usePkce=true)
  const authResult = sdk.auth.createOAAuthUrl(redirectUri, undefined, undefined, true);

  console.log('Authorization URL with Auto PKCE:', authResult.url);
  console.log('Generated State:', authResult.state);
  console.log('Auto-Generated PKCE:', authResult.pkce);

  // IMPORTANT: Store the auto-generated PKCE and state
  console.log('\n⚠️  IMPORTANT: Store these auto-generated values:');
  console.log('- Code Verifier:', authResult.pkce?.code_verifier);
  console.log('- State:', authResult.state);

  return authResult;
}

// Example 3: Complete flow - Authorization + Token Exchange
async function completeOAFlow() {
  console.log('\n=== Complete OA Flow with PKCE ===');
  
  const redirectUri = 'https://your-app.com/callback';
  
  // Step 1: Generate PKCE and create auth URL
  const pkce = sdk.auth.generatePKCE();
  const authResult = sdk.auth.createOAAuthUrl(redirectUri, 'my_oa_flow', pkce);
  
  console.log('1. Redirect user to:', authResult.url);
  console.log('2. Store state and code_verifier:', {
    state: authResult.state,
    code_verifier: pkce.code_verifier
  });
  
  // Step 2: After user authorizes and returns with code
  // (This would happen in your callback handler)
  const simulateCallback = async (authorizationCode: string, returnedState: string) => {
    console.log('\n3. User returned with authorization code');
    
    // Verify state matches
    if (returnedState !== authResult.state) {
      throw new Error('State mismatch - possible CSRF attack');
    }
    
    // Step 3: Exchange code for access token with PKCE
    try {
      const tokenResult = await sdk.auth.getOAAccessToken({
        app_id: 'your_app_id',
        app_secret: 'your_app_secret',
        code: authorizationCode,
        redirect_uri: redirectUri,
        code_verifier: pkce.code_verifier, // Include code_verifier for PKCE
      });
      
      console.log('4. Successfully obtained access token:', {
        access_token: tokenResult.access_token.substring(0, 20) + '...',
        expires_in: tokenResult.expires_in,
        has_refresh_token: !!tokenResult.refresh_token
      });
      
      return tokenResult;
    } catch (error) {
      console.error('Failed to exchange code for token:', error);
      throw error;
    }
  };
  
  // Simulate the callback (in real app, this would be handled by your callback endpoint)
  console.log('\n--- Simulating callback ---');
  // await simulateCallback('simulated_auth_code', authResult.state);
}

// Example 4: Using getAuthUrls method
async function getAuthUrlsExample() {
  console.log('\n=== Get Auth URLs ===');
  
  const redirectUri = 'https://your-app.com/callback';
  const pkce = sdk.auth.generatePKCE();
  
  const authUrls = sdk.auth.getAuthUrls(redirectUri, pkce);
  
  console.log('All auth URLs:', {
    oa_auth_url: authUrls.oa_auth_url,
    social_auth_url: authUrls.social_auth_url,
    token_url: authUrls.token_url,
    refresh_url: authUrls.refresh_url
  });
}

// Run examples
async function runExamples() {
  try {
    await basicOAAuth();
    await oaAuthWithPKCE();
    await oaAuthWithAutoPKCE();
    await completeOAFlow();
    await getAuthUrlsExample();
  } catch (error) {
    console.error('Example error:', error);
  }
}

// Export for use in other files
export {
  basicOAAuth,
  oaAuthWithPKCE,
  oaAuthWithAutoPKCE,
  completeOAFlow,
  getAuthUrlsExample,
  runExamples
};

// Run if this file is executed directly
if (require.main === module) {
  runExamples();
}
