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

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

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

const tempDirs: string[] = [];

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

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

describe("1688 profile lock", () => {
  it("creates and releases a lock file in the profile directory", async () => {
    const profileDir = await makeTempDir();

    const lock = await acquire1688ProfileLock(profileDir, {
      pid: 12345,
      now: () => 1_700_000_000_000,
    });

    const payload = JSON.parse(await readFile(path.join(profileDir, ".alphapulse-profile.lock"), "utf8"));
    expect(payload.pid).toBe(12345);
    expect(payload.token).toBe(lock.token);

    await lock.release();

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

  it("clears stale locks when the owner process is gone", async () => {
    const profileDir = await makeTempDir();
    await writeFile(
      path.join(profileDir, ".alphapulse-profile.lock"),
      JSON.stringify({ pid: 999999, token: "old", createdAt: 1_700_000_000_000 }),
      "utf8",
    );

    const lock = await acquire1688ProfileLock(profileDir, {
      pid: 12345,
      now: () => 1_700_000_001_000,
      isProcessAlive: () => false,
    });

    const payload = JSON.parse(await readFile(path.join(profileDir, ".alphapulse-profile.lock"), "utf8"));
    expect(payload.pid).toBe(12345);
    expect(payload.token).toBe(lock.token);

    await lock.release();
  });

  it("times out when another live process owns the profile", async () => {
    const profileDir = await makeTempDir();
    let currentTime = 1_700_000_001_000;
    await writeFile(
      path.join(profileDir, ".alphapulse-profile.lock"),
      JSON.stringify({ pid: 11111, token: "live", createdAt: 1_700_000_000_000 }),
      "utf8",
    );

    await expect(acquire1688ProfileLock(profileDir, {
      pid: 12345,
      now: () => {
        currentTime += 2;
        return currentTime;
      },
      timeoutMs: 5,
      retryMs: 1,
      isProcessAlive: () => true,
      sleep: async () => {},
    })).rejects.toThrow(/profile is locked/i);
  });
});
