#!/usr/bin/env node

/**
 * OAuth2 Setup Script for Google Workspace
 *
 * Usage: node oauth_setup.js <account-alias>
 * Example: node oauth_setup.js psd
 *
 * This script:
 * 1. Starts a local server to receive OAuth callback
 * 2. Opens browser to Google consent page
 * 3. Exchanges auth code for tokens
 * 4. Outputs tokens as JSON (to be stored by token_manager.js)
 *
 * Prerequisites:
 * - .env file with GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET
 * - npm install googleapis open dotenv
 */

const { google } = require('googleapis');
const http = require('http');
const url = require('url');
const openModule = require('open');
const open = openModule.default || openModule;
const path = require('path');

// Load environment variables from iCloud secrets
const os = require('os');
const ENV_PATH = path.join(
  os.homedir(),
  'Library/Mobile Documents/com~apple~CloudDocs/Geoffrey/secrets/.env'
);
require('dotenv').config({ path: ENV_PATH });

// Configuration
const REDIRECT_PORT = process.env.OAUTH_REDIRECT_PORT || 3000;
const REDIRECT_URI = `http://localhost:${REDIRECT_PORT}/oauth2callback`;

// Full scope list for complete Google Workspace access
const SCOPES = [
  // Gmail
  'https://www.googleapis.com/auth/gmail.readonly',
  'https://www.googleapis.com/auth/gmail.send',
  'https://www.googleapis.com/auth/gmail.compose',
  'https://www.googleapis.com/auth/gmail.modify',
  'https://www.googleapis.com/auth/gmail.labels',

  // Calendar
  'https://www.googleapis.com/auth/calendar',
  'https://www.googleapis.com/auth/calendar.events',

  // Drive
  'https://www.googleapis.com/auth/drive',
  'https://www.googleapis.com/auth/drive.file',

  // Docs, Sheets, Slides
  'https://www.googleapis.com/auth/documents',
  'https://www.googleapis.com/auth/spreadsheets',
  'https://www.googleapis.com/auth/presentations',

  // Forms
  'https://www.googleapis.com/auth/forms.body',
  'https://www.googleapis.com/auth/forms.responses.readonly',

  // Chat
  'https://www.googleapis.com/auth/chat.spaces',
  'https://www.googleapis.com/auth/chat.messages',
  'https://www.googleapis.com/auth/chat.memberships.readonly',

  // Tasks
  'https://www.googleapis.com/auth/tasks',

  // Keep (Note: Keep API has limited availability)
  // 'https://www.googleapis.com/auth/keep',

  // User info (to identify which account)
  'https://www.googleapis.com/auth/userinfo.email',
  'https://www.googleapis.com/auth/userinfo.profile',

  // Admin Directory (to look up user names)
  'https://www.googleapis.com/auth/admin.directory.user.readonly',
];

async function main() {
  const accountAlias = process.argv[2];

  if (!accountAlias) {
    console.error(JSON.stringify({
      error: 'Missing account alias',
      usage: 'node oauth_setup.js <account-alias>',
      example: 'node oauth_setup.js psd'
    }));
    process.exit(1);
  }

  // Load client credentials from environment
  const client_id = process.env.GOOGLE_CLIENT_ID;
  const client_secret = process.env.GOOGLE_CLIENT_SECRET;

  if (!client_id || !client_secret) {
    console.error(JSON.stringify({
      error: 'Missing credentials in .env',
      instructions: [
        '1. Go to Google Cloud Console',
        '2. Create OAuth 2.0 Client ID (Desktop app)',
        '3. Copy client ID and secret to skills/google-workspace/.env',
        '4. See .env.example for format'
      ]
    }));
    process.exit(1);
  }

  // Create OAuth2 client
  const oauth2Client = new google.auth.OAuth2(
    client_id,
    client_secret,
    REDIRECT_URI
  );

  // Generate auth URL
  const authUrl = oauth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES,
    prompt: 'consent', // Force to get refresh token
  });

  // Start local server to receive callback
  const server = http.createServer(async (req, res) => {
    try {
      const parsedUrl = url.parse(req.url, true);

      if (parsedUrl.pathname === '/oauth2callback') {
        const code = parsedUrl.query.code;

        if (!code) {
          res.writeHead(400);
          res.end('Missing authorization code');
          return;
        }

        // Exchange code for tokens
        const { tokens } = await oauth2Client.getToken(code);

        // Get user info to confirm which account
        oauth2Client.setCredentials(tokens);
        const oauth2 = google.oauth2({ version: 'v2', auth: oauth2Client });
        const userInfo = await oauth2.userinfo.get();

        // Send success response to browser
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end(`
          <html>
            <body style="font-family: sans-serif; padding: 40px; text-align: center;">
              <h1>✅ Authorization Successful</h1>
              <p>Account: <strong>${userInfo.data.email}</strong></p>
              <p>Alias: <strong>${accountAlias}</strong></p>
              <p>You can close this window.</p>
            </body>
          </html>
        `);

        // Output tokens as JSON
        console.log(JSON.stringify({
          success: true,
          account: accountAlias,
          email: userInfo.data.email,
          tokens: {
            access_token: tokens.access_token,
            refresh_token: tokens.refresh_token,
            token_type: tokens.token_type,
            expiry_date: tokens.expiry_date,
          }
        }, null, 2));

        // Close server
        server.close();
      }
    } catch (error) {
      res.writeHead(500);
      res.end('Authorization failed');
      console.error(JSON.stringify({
        error: 'Token exchange failed',
        message: error.message
      }));
      server.close();
      process.exit(1);
    }
  });

  server.listen(REDIRECT_PORT, async () => {
    console.error(`Opening browser for ${accountAlias} account authorization...`);
    console.error(`If browser doesn't open, visit: ${authUrl}`);
    await open(authUrl);
  });

  // Timeout after 5 minutes
  setTimeout(() => {
    console.error(JSON.stringify({
      error: 'Authorization timeout',
      message: 'No response received within 5 minutes'
    }));
    server.close();
    process.exit(1);
  }, 5 * 60 * 1000);
}

main().catch(error => {
  console.error(JSON.stringify({
    error: 'Setup failed',
    message: error.message
  }));
  process.exit(1);
});
