import { mkdir, writeFile } from "fs/promises";
import path from "path";
import type { Page } from "playwright";
import { getActiveAccountConnectionSettings } from "@/lib/account-connection-settings";

const DEBUG_DIR = path.join(process.cwd(), "data", "debug-runs");

export interface DebugRun {
  id: string;
  label: string;
  dir: string;
  enabled: boolean;
}

export async function isPlaywrightDebugEnabled(): Promise<boolean> {
  if (process.env.THREADS_DEBUG === "true") return true;
  try {
    const connection = await getActiveAccountConnectionSettings();
    return connection.playwrightDebug === true;
  } catch {
    return false;
  }
}

export async function shouldRunHeaded(): Promise<boolean> {
  if (process.env.PLAYWRIGHT_HEADLESS === "false") return true;
  if (process.env.PLAYWRIGHT_HEADLESS === "true") return false;
  return isPlaywrightDebugEnabled();
}

/** 發布預設用可見瀏覽器，較不容易被擋、也方便手動完成 Instagram 授權 */
export async function shouldRunHeadedForPublish(): Promise<boolean> {
  if (process.env.PLAYWRIGHT_HEADLESS === "false") return true;
  if (process.env.PLAYWRIGHT_HEADLESS === "true") return false;
  try {
    const connection = await getActiveAccountConnectionSettings();
    if (connection.playwrightDebug) return true;
    return connection.publishHeaded ?? true;
  } catch {
    return true;
  }
}

export function getPlaywrightSlowMo(): number {
  const raw = process.env.PLAYWRIGHT_SLOW_MO;
  if (raw) {
    const parsed = Number(raw);
    if (!Number.isNaN(parsed) && parsed >= 0) return parsed;
  }
  return 0;
}

export async function createDebugRun(
  label: string,
  options?: { force?: boolean }
): Promise<DebugRun | null> {
  const enabled = options?.force === true || await isPlaywrightDebugEnabled();
  if (!enabled) return null;

  const id = `${Date.now()}-${label.replace(/[^a-zA-Z0-9_-]+/g, "-").slice(0, 40)}`;
  const dir = path.join(DEBUG_DIR, id);
  await mkdir(dir, { recursive: true });
  await writeFile(
    path.join(dir, "manifest.json"),
    JSON.stringify({ id, label, startedAt: new Date().toISOString(), steps: [] }, null, 2)
  );

  console.log(`[threads-debug] run=${id} label=${label}`);
  return { id, label, dir, enabled };
}

export async function captureDebugStep(
  page: Page,
  run: DebugRun | null | undefined,
  step: string,
  meta?: Record<string, unknown>
) {
  if (!run?.enabled) return;

  const safeStep = step.replace(/[^a-zA-Z0-9_-]+/g, "-").slice(0, 80);
  const timestamp = new Date().toISOString();
  const shotPath = path.join(run.dir, `${safeStep}.png`);

  try {
    await page.screenshot({ path: shotPath, fullPage: true });
  } catch (error) {
    console.warn(`[threads-debug] screenshot failed (${step})`, error);
  }

  try {
    const manifestPath = path.join(run.dir, "manifest.json");
    const { readFile } = await import("fs/promises");
    const manifest = JSON.parse(await readFile(manifestPath, "utf8")) as {
      steps: Array<Record<string, unknown>>;
    };
    manifest.steps.push({
      step,
      at: timestamp,
      url: page.url(),
      title: await page.title().catch(() => ""),
      screenshot: `${safeStep}.png`,
      ...meta,
    });
    await writeFile(manifestPath, JSON.stringify(manifest, null, 2));
  } catch (error) {
    console.warn(`[threads-debug] manifest update failed (${step})`, error);
  }

  console.log(`[threads-debug] ${run.id} · ${step} · ${page.url()}`);
}

export function debugDirPath(): string {
  return DEBUG_DIR;
}
