#!/usr/bin/env node
// aether-browser: Playwright helper for Aether web UI automation
// Usage: aether-browser <action> [args...]
//
// Actions:
//   login              - Login and save session cookies
//   screenshot <path>  - Take screenshot of current page
//   haproxy-status     - Check HAProxy infrastructure status
//   haproxy-images     - List HAProxy images
//   navigate <url>     - Navigate to URL and return page content
//   eval <js>          - Evaluate JavaScript on current page
//
// Environment:
//   AETHER_URL              - Aether base URL (default: https://192.168.102.160:8443)
//   AETHER_ADMIN_PASSWORD   - Admin password (required)
//   AETHER_COOKIE_FILE      - Cookie persistence file (default: /tmp/aether-cookies.json)
//   HEADLESS                - Set to "false" for visible browser (default: true)

const { chromium } = require('playwright-core');
const fs = require('fs');
const path = require('path');

const AETHER_URL = process.env.AETHER_URL || 'https://192.168.102.160:8443';
const PASSWORD = process.env.AETHER_ADMIN_PASSWORD;
const COOKIE_FILE = process.env.AETHER_COOKIE_FILE || '/tmp/aether-cookies.json';
const HEADLESS = process.env.HEADLESS !== 'false';
const SCREENSHOT_DIR = '/tmp';

if (!PASSWORD) {
  console.error('ERROR: AETHER_ADMIN_PASSWORD not set. Source the env file first.');
  process.exit(1);
}

async function getBrowser() {
  // Use Playwright's bundled Chromium
  const browserPath = require('playwright-core').chromium.executablePath();
  return await chromium.launch({
    headless: HEADLESS,
    executablePath: browserPath,
    args: ['--ignore-certificate-errors', '--no-sandbox'],
  });
}

async function getContextWithCookies(browser) {
  const context = await browser.newContext({
    ignoreHTTPSErrors: true,
    viewport: { width: 1280, height: 800 },
  });

  // Restore cookies if available
  if (fs.existsSync(COOKIE_FILE)) {
    try {
      const cookies = JSON.parse(fs.readFileSync(COOKIE_FILE, 'utf8'));
      await context.addCookies(cookies);
    } catch (e) {
      // Stale cookies, will re-login
    }
  }

  return context;
}

async function saveCookies(context) {
  const cookies = await context.cookies();
  fs.writeFileSync(COOKIE_FILE, JSON.stringify(cookies, null, 2));
}

async function login(page) {
  console.log(`Navigating to ${AETHER_URL}/...`);
  await page.goto(`${AETHER_URL}/`, { waitUntil: 'networkidle' });

  // Check if already logged in
  const url = page.url();
  if (!url.includes('login') && !await page.locator('input[name="csrf_token"]').count()) {
    console.log('Already logged in (session cookies valid).');
    return true;
  }

  console.log('Login page detected. Filling credentials...');

  // Fill the login form
  await page.fill('input[name="username"]', 'admin');
  await page.fill('input[name="password"]', PASSWORD);

  // Submit
  await page.click('button[type="submit"], input[type="submit"]');

  // Wait for navigation after login
  await page.waitForLoadState('networkidle');

  // Check success
  const afterUrl = page.url();
  if (afterUrl.includes('login')) {
    console.error('ERROR: Login failed - still on login page.');
    await page.screenshot({ path: `${SCREENSHOT_DIR}/aether-login-fail.png` });
    console.error(`Screenshot saved to ${SCREENSHOT_DIR}/aether-login-fail.png`);
    return false;
  }

  console.log(`Login successful. Redirected to: ${afterUrl}`);
  return true;
}

async function doAction(action, args) {
  const browser = await getBrowser();
  const context = await getContextWithCookies(browser);
  const page = await context.newPage();

  try {
    switch (action) {
      case 'login': {
        const success = await login(page);
        if (success) {
          await saveCookies(context);
          console.log(`Session cookies saved to ${COOKIE_FILE}`);
        }
        break;
      }

      case 'screenshot': {
        const loginOk = await login(page);
        if (!loginOk) break;
        await saveCookies(context);

        const targetUrl = args[0] || '/';
        if (targetUrl.startsWith('/')) {
          await page.goto(`${AETHER_URL}${targetUrl}`, { waitUntil: 'networkidle' });
        }

        const outPath = args[1] || `${SCREENSHOT_DIR}/aether-screenshot.png`;
        await page.screenshot({ path: outPath, fullPage: true });
        console.log(`Screenshot saved to ${outPath}`);
        break;
      }

      case 'haproxy-status': {
        const loginOk = await login(page);
        if (!loginOk) break;
        await saveCookies(context);

        // Navigate to HAProxy infrastructure page
        console.log('Navigating to HAProxy management...');
        await page.goto(`${AETHER_URL}/haproxy`, { waitUntil: 'networkidle' });
        await page.screenshot({ path: `${SCREENSHOT_DIR}/aether-haproxy.png`, fullPage: true });
        console.log(`Screenshot: ${SCREENSHOT_DIR}/aether-haproxy.png`);

        // Try to extract status info from the page
        const content = await page.textContent('body');
        // Print relevant sections
        const lines = content.split('\n').filter(l => l.trim());
        console.log('\n--- Page content (filtered) ---');
        for (const line of lines.slice(0, 50)) {
          console.log(line.trim());
        }
        break;
      }

      case 'haproxy-images': {
        const loginOk = await login(page);
        if (!loginOk) break;
        await saveCookies(context);

        console.log('Fetching HAProxy images...');
        // Use the session to make an API call
        const response = await page.evaluate(async () => {
          const resp = await fetch('/haproxy/images', {
            credentials: 'same-origin',
          });
          return { status: resp.status, body: await resp.text() };
        });
        console.log(`Status: ${response.status}`);
        console.log(response.body);
        break;
      }

      case 'navigate': {
        const loginOk = await login(page);
        if (!loginOk) break;
        await saveCookies(context);

        const navUrl = args[0] || '/';
        const fullUrl = navUrl.startsWith('http') ? navUrl : `${AETHER_URL}${navUrl}`;
        console.log(`Navigating to ${fullUrl}...`);
        await page.goto(fullUrl, { waitUntil: 'networkidle' });

        const outPath = `${SCREENSHOT_DIR}/aether-navigate.png`;
        await page.screenshot({ path: outPath, fullPage: true });
        console.log(`Screenshot: ${outPath}`);

        const title = await page.title();
        console.log(`Title: ${title}`);
        console.log(`URL: ${page.url()}`);
        break;
      }

      case 'api-get': {
        const loginOk = await login(page);
        if (!loginOk) break;
        await saveCookies(context);

        const endpoint = args[0];
        if (!endpoint) {
          console.error('Usage: aether-browser api-get <endpoint>');
          break;
        }

        const response = await page.evaluate(async (url) => {
          const resp = await fetch(url, { credentials: 'same-origin' });
          const text = await resp.text();
          return { status: resp.status, contentType: resp.headers.get('content-type'), body: text };
        }, endpoint);

        console.log(`GET ${endpoint} -> ${response.status}`);
        if (response.contentType && response.contentType.includes('json')) {
          try {
            console.log(JSON.stringify(JSON.parse(response.body), null, 2));
          } catch {
            console.log(response.body);
          }
        } else {
          console.log(response.body);
        }
        break;
      }

      case 'api-post': {
        const loginOk = await login(page);
        if (!loginOk) break;
        await saveCookies(context);

        const endpoint = args[0];
        const bodyJson = args[1];
        if (!endpoint || !bodyJson) {
          console.error('Usage: aether-browser api-post <endpoint> <json-body>');
          break;
        }

        // Get CSRF token from meta tag or cookie
        const csrfToken = await page.evaluate(() => {
          const meta = document.querySelector('meta[name="csrf-token"]');
          if (meta) return meta.getAttribute('content');
          // Try from cookie
          const match = document.cookie.match(/csrf_token=([^;]+)/);
          return match ? match[1] : '';
        });

        const response = await page.evaluate(async ({ url, body, csrf }) => {
          const headers = {
            'Content-Type': 'application/json',
          };
          if (csrf) {
            headers['X-CSRFToken'] = csrf;
            headers['X-CSRF-Token'] = csrf;
          }
          const resp = await fetch(url, {
            method: 'POST',
            credentials: 'same-origin',
            headers,
            body,
          });
          const text = await resp.text();
          return { status: resp.status, body: text };
        }, { url: endpoint, body: bodyJson, csrf: csrfToken });

        console.log(`POST ${endpoint} -> ${response.status}`);
        try {
          console.log(JSON.stringify(JSON.parse(response.body), null, 2));
        } catch {
          console.log(response.body);
        }
        break;
      }

      case 'eval': {
        const loginOk = await login(page);
        if (!loginOk) break;
        await saveCookies(context);

        const js = args.join(' ');
        const result = await page.evaluate(js);
        console.log(JSON.stringify(result, null, 2));
        break;
      }

      default:
        console.error(`Unknown action: ${action}`);
        console.error('Actions: login, screenshot, haproxy-status, haproxy-images, navigate, api-get, api-post, eval');
        process.exit(1);
    }
  } finally {
    await browser.close();
  }
}

// Main
const [action, ...args] = process.argv.slice(2);
if (!action) {
  console.error('Usage: aether-browser <action> [args...]');
  console.error('Actions: login, screenshot, haproxy-status, haproxy-images, navigate, api-get, api-post, eval');
  process.exit(1);
}

doAction(action, args).catch(err => {
  console.error('Fatal error:', err.message);
  process.exit(1);
});
