#!/usr/bin/env bun
/**
 * AnyClip Monetization API Interception Script
 *
 * This script launches a visible browser, allows manual login,
 * and captures all API traffic on the monetization page.
 *
 * Usage: bun scripts/intercept-monetization.ts
 *
 * Press Ctrl+C to stop and save captured data.
 */

import { chromium, type Page, type Request, type Response } from "playwright";
import { writeFileSync } from "fs";

interface CapturedRequest {
  timestamp: string;
  url: string;
  method: string;
  headers: Record<string, string>;
  requestBody: string | null;
  responseStatus: number | null;
  responseHeaders: Record<string, string> | null;
  responseBody: string | null;
  duration: number | null;
}

const capturedRequests: CapturedRequest[] = [];
const pendingRequests = new Map<
  Request,
  { startTime: number; captured: CapturedRequest }
>();

const OUTPUT_FILE = "captured-apis.json";
const BASE_URL = "https://videomanager.anyclip.com";
const MONETIZATION_PATH = "/analytics-new/monetization";

// Filter for API requests we care about
function isApiRequest(url: string): boolean {
  // Capture GraphQL, REST API calls, and data endpoints
  const apiPatterns = [
    "/graphql",
    "/api/",
    "/analytics",
    "/monetization",
    "/v1/",
    "/v2/",
    "anyclip.com",
  ];

  // Exclude static assets
  const excludePatterns = [
    ".js",
    ".css",
    ".png",
    ".jpg",
    ".jpeg",
    ".gif",
    ".svg",
    ".ico",
    ".woff",
    ".woff2",
    ".ttf",
    ".eot",
    "/static/",
    "fonts.googleapis.com",
    "google-analytics.com",
    "googletagmanager.com",
  ];

  const urlLower = url.toLowerCase();

  if (excludePatterns.some((pattern) => urlLower.includes(pattern))) {
    return false;
  }

  return apiPatterns.some((pattern) => urlLower.includes(pattern));
}

function saveCaptures(): void {
  const output = {
    capturedAt: new Date().toISOString(),
    totalRequests: capturedRequests.length,
    requests: capturedRequests,
  };

  writeFileSync(OUTPUT_FILE, JSON.stringify(output, null, 2));
  console.log(`\n✅ Saved ${capturedRequests.length} requests to ${OUTPUT_FILE}`);
}

async function handleRequest(request: Request): Promise<void> {
  const url = request.url();

  if (!isApiRequest(url)) {
    return;
  }

  const captured: CapturedRequest = {
    timestamp: new Date().toISOString(),
    url,
    method: request.method(),
    headers: request.headers(),
    requestBody: request.postData() || null,
    responseStatus: null,
    responseHeaders: null,
    responseBody: null,
    duration: null,
  };

  pendingRequests.set(request, {
    startTime: Date.now(),
    captured,
  });

  console.log(`📤 ${request.method()} ${url}`);
}

async function handleResponse(response: Response): Promise<void> {
  const request = response.request();
  const pending = pendingRequests.get(request);

  if (!pending) {
    return;
  }

  const { startTime, captured } = pending;

  captured.responseStatus = response.status();
  captured.responseHeaders = response.headers();
  captured.duration = Date.now() - startTime;

  try {
    const contentType = response.headers()["content-type"] || "";
    if (
      contentType.includes("application/json") ||
      contentType.includes("text/")
    ) {
      captured.responseBody = await response.text();
    } else {
      captured.responseBody = `[Binary content: ${contentType}]`;
    }
  } catch (error) {
    captured.responseBody = `[Error reading response: ${error}]`;
  }

  capturedRequests.push(captured);
  pendingRequests.delete(request);

  console.log(
    `📥 ${response.status()} ${captured.url} (${captured.duration}ms)`
  );
}

async function main(): Promise<void> {
  console.log("🚀 AnyClip Monetization API Interceptor");
  console.log("=========================================\n");

  console.log("Launching browser...");
  const browser = await chromium.launch({
    headless: false,
    args: ["--start-maximized"],
  });

  const context = await browser.newContext({
    viewport: null, // Use full window size
  });

  const page = await context.newPage();

  // Set up request/response interception
  page.on("request", handleRequest);
  page.on("response", handleResponse);

  // Navigate to AnyClip
  console.log(`\nNavigating to ${BASE_URL}...`);
  await page.goto(BASE_URL);

  console.log("\n" + "=".repeat(50));
  console.log("👤 Please log in manually in the browser window");
  console.log("=".repeat(50) + "\n");

  // Wait for login - user must navigate to a protected page
  console.log("Waiting for authentication...");
  console.log("(Navigate to any page after logging in, or the script will auto-detect)\n");

  // Wait for URL to change to a protected route (not login/logout)
  await page.waitForFunction(
    () => {
      const path = window.location.pathname;
      // Must be on a real app page, not login/logout/root
      const protectedRoutes = [
        "/dashboard",
        "/analytics",
        "/video",
        "/library",
        "/settings",
        "/playlists",
        "/players",
      ];
      return protectedRoutes.some((route) => path.startsWith(route));
    },
    { timeout: 300000 } // 5 minute timeout for login
  );

  console.log("✅ Authentication detected!\n");

  // Navigate to monetization page
  const monetizationUrl = `${BASE_URL}${MONETIZATION_PATH}`;
  console.log(`Navigating to ${monetizationUrl}...`);

  try {
    await page.goto(monetizationUrl, { waitUntil: "domcontentloaded" });
  } catch (error) {
    // Navigation might fail if page redirects - that's okay
    console.log("Navigation completed (may have redirected)");
  }

  // Wait for page to stabilize
  await page.waitForTimeout(2000);
  await page.waitForLoadState("networkidle").catch(() => {});

  console.log("\n" + "=".repeat(50));
  console.log("📊 Now capturing API traffic on the Monetization page");
  console.log("   Interact with filters, date ranges, etc.");
  console.log("   Press Ctrl+C when done to save captured data");
  console.log("=".repeat(50) + "\n");

  // Handle Ctrl+C gracefully
  process.on("SIGINT", async () => {
    console.log("\n\n🛑 Stopping capture...");
    saveCaptures();
    await browser.close();
    process.exit(0);
  });

  // Keep the script running
  await new Promise(() => {}); // Never resolves - keeps script alive
}

main().catch((error) => {
  console.error("Error:", error);
  saveCaptures();
  process.exit(1);
});
