import { existsSync } from "node:fs";
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

const mocks = vi.hoisted(() => ({
  close: vi.fn(async () => {}),
  launchPersistentContext: vi.fn(),
}));

vi.mock("playwright", () => ({
  chromium: {
    launchPersistentContext: mocks.launchPersistentContext,
  },
}));

import { launch1688PersistentContext } from "./persistent-context.js";

const tempDirs: string[] = [];

async function makeTempDir() {
  const dir = await mkdtemp(path.join(os.tmpdir(), "1688-persistent-context-"));
  tempDirs.push(dir);
  return dir;
}

beforeEach(() => {
  mocks.close.mockReset();
  mocks.launchPersistentContext.mockReset();
  mocks.launchPersistentContext.mockResolvedValue({
    close: mocks.close,
  });
});

afterEach(async () => {
  await Promise.all(tempDirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true })));
});

describe("launch1688PersistentContext", () => {
  it("strips volatile Chrome files, preserves session data, and releases the profile lock on close", async () => {
    const profileDir = await makeTempDir();
    await mkdir(path.join(profileDir, "Default"), { recursive: true });
    await writeFile(path.join(profileDir, "SingletonLock"), "lock", "utf8");
    await writeFile(path.join(profileDir, "Default", "Cookies"), "cookie-db", "utf8");

    const context = await launch1688PersistentContext(profileDir, {
      contextOptions: {
        headless: true,
        args: ["--disable-blink-features=AutomationControlled"],
      },
      lock: {
        pid: 12345,
        now: () => 1_700_000_000_000,
      },
    });

    expect(existsSync(path.join(profileDir, "SingletonLock"))).toBe(false);
    await expect(readFile(path.join(profileDir, "Default", "Cookies"), "utf8"))
      .resolves.toBe("cookie-db");
    expect(existsSync(path.join(profileDir, ".alphapulse-profile.lock"))).toBe(true);
    expect(mocks.launchPersistentContext).toHaveBeenCalledWith(
      profileDir,
      expect.objectContaining({
        channel: "chrome",
        headless: true,
        locale: "zh-CN",
        viewport: { width: 1440, height: 960 },
      }),
    );

    await context.close();

    expect(mocks.close).toHaveBeenCalledTimes(1);
    expect(existsSync(path.join(profileDir, ".alphapulse-profile.lock"))).toBe(false);
  });
});
