import { mkdir, readdir, rm } from "node:fs/promises";
import path from "node:path";

import { chromium } from "playwright";

import { acquire1688ProfileLock } from "./profile-lock.js";

const VOLATILE_CHROME_PROFILE_FILES = new Set([
  "SingletonCookie",
  "SingletonLock",
  "SingletonSocket",
]);

async function stripVolatileChromeProfileFiles(dirPath) {
  let entries;
  try {
    entries = await readdir(dirPath, { withFileTypes: true });
  } catch {
    return;
  }

  await Promise.all(entries.map(async (entry) => {
    const entryPath = path.join(dirPath, entry.name);
    if (VOLATILE_CHROME_PROFILE_FILES.has(entry.name)) {
      await rm(entryPath, { recursive: true, force: true });
      return;
    }
    if (entry.isDirectory()) {
      await stripVolatileChromeProfileFiles(entryPath);
    }
  }));
}

export async function launch1688PersistentContext(profileDir, options = {}) {
  await mkdir(profileDir, { recursive: true });
  await stripVolatileChromeProfileFiles(profileDir);
  const lock = await acquire1688ProfileLock(profileDir, options.lock);

  try {
    const context = await chromium.launchPersistentContext(profileDir, {
      channel: process.env.PLAYWRIGHT_CHROME_CHANNEL || "chrome",
      locale: "zh-CN",
      viewport: { width: 1440, height: 960 },
      ...options.contextOptions,
    });
    const originalClose = context.close.bind(context);
    let closed = false;
    context.close = async (...args) => {
      if (closed) {
        return;
      }
      closed = true;
      try {
        await originalClose(...args);
      } finally {
        await lock.release();
      }
    };
    return context;
  } catch (error) {
    await lock.release();
    throw error;
  }
}
