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

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DEFAULT_SEARCH_TASK_RUNTIME_ROOT = path.join(__dirname, "..", ".runtime", "search-tasks");
const VOLATILE_CHROME_PROFILE_FILES = new Set([
  "SingletonCookie",
  "SingletonLock",
  "SingletonSocket",
]);

export function getSearchTaskRuntimePaths(taskId: string, runtimeRootDir = DEFAULT_SEARCH_TASK_RUNTIME_ROOT) {
  const rootDir = path.join(runtimeRootDir, taskId);
  return {
    rootDir,
    profileDir: path.join(rootDir, "profile"),
    outputRoot: path.join(rootDir, "output"),
  };
}

async function directoryHasContents(dirPath: string) {
  try {
    const entries = await readdir(dirPath);
    return entries.length > 0;
  } catch {
    return false;
  }
}

async function stripVolatileChromeProfileFiles(dirPath: string) {
  let entries: Awaited<ReturnType<typeof readdir>>;
  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 prepareSearchTaskRuntimeProfile(params: {
  taskId: string;
  accountProfileDir: string;
  runtimeRootDir?: string;
}) {
  const runtimePaths = getSearchTaskRuntimePaths(params.taskId, params.runtimeRootDir);
  await mkdir(runtimePaths.rootDir, { recursive: true });
  await mkdir(runtimePaths.outputRoot, { recursive: true });

  if (await directoryHasContents(runtimePaths.profileDir)) {
    await stripVolatileChromeProfileFiles(runtimePaths.profileDir);
    return runtimePaths;
  }

  await rm(runtimePaths.profileDir, { recursive: true, force: true });

  if (existsSync(params.accountProfileDir) && await directoryHasContents(params.accountProfileDir)) {
    await cp(params.accountProfileDir, runtimePaths.profileDir, { recursive: true, force: true });
  } else {
    await mkdir(runtimePaths.profileDir, { recursive: true });
  }

  await stripVolatileChromeProfileFiles(runtimePaths.profileDir);
  return runtimePaths;
}

export async function syncSearchTaskRuntimeProfileToAccount(params: {
  taskId: string;
  accountProfileDir: string;
  runtimeRootDir?: string;
}) {
  const runtimePaths = getSearchTaskRuntimePaths(params.taskId, params.runtimeRootDir);
  if (!(await directoryHasContents(runtimePaths.profileDir))) {
    return false;
  }

  await stripVolatileChromeProfileFiles(runtimePaths.profileDir);
  await rm(params.accountProfileDir, { recursive: true, force: true });
  await cp(runtimePaths.profileDir, params.accountProfileDir, { recursive: true, force: true });
  await stripVolatileChromeProfileFiles(params.accountProfileDir);
  return true;
}
