import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";

const connect = vi.fn().mockResolvedValue(undefined);
const quit = vi.fn().mockResolvedValue(undefined);
const setex = vi.fn().mockResolvedValue("OK");
const get = vi.fn().mockResolvedValue(null);

vi.mock("ioredis", () => ({
  default: vi.fn().mockImplementation(() => ({
    connect,
    quit,
    setex,
    get,
  })),
}));

import {
  resolveQuoteSessionStoragePath,
  saveQuoteSessionFromContext,
} from "@/lib/rpa/quote-session-store";

describe("quote-session-store", () => {
  const prevCwd = process.cwd();
  const prevRedisUrl = process.env.REDIS_URL;
  let tmpDir = "";

  afterEach(() => {
    process.chdir(prevCwd);
    if (prevRedisUrl === undefined) {
      delete process.env.REDIS_URL;
    } else {
      process.env.REDIS_URL = prevRedisUrl;
    }
    if (tmpDir) {
      fs.rmSync(tmpDir, { recursive: true, force: true });
      tmpDir = "";
    }
    vi.clearAllMocks();
  });

  it("saveQuoteSessionFromContext 写入本地文件并返回 sessionId", async () => {
    tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "quote-session-"));
    process.chdir(tmpDir);
    process.env.REDIS_URL = "redis://127.0.0.1:6379";

    const storageState = vi.fn().mockImplementation(async ({ path: outPath }: { path: string }) => {
      fs.mkdirSync(path.dirname(outPath), { recursive: true });
      fs.writeFileSync(outPath, "{}", "utf8");
    });
    const sessionId = await saveQuoteSessionFromContext(
      { storageState } as never,
      {
        pickup: {
          street: "123 Main",
          city: "LA",
          state: "CA",
          zip: "90001",
        },
        delivery: {
          street: "456 Oak",
          city: "Dallas",
          state: "TX",
          zip: "75201",
        },
      },
    );

    expect(sessionId).toMatch(
      /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
    );
    expect(
      fs.existsSync(path.join(tmpDir, ".rpa", "sessions", `${sessionId}.json`)),
    ).toBe(true);
    expect(setex).toHaveBeenCalled();
  });

  it("resolveQuoteSessionStoragePath Redis 失败时回退本地文件", async () => {
    tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "quote-session-"));
    process.chdir(tmpDir);
    process.env.REDIS_URL = "redis://127.0.0.1:6379";
    connect.mockRejectedValueOnce(new Error("redis down"));

    const sessionId = "11111111-1111-4111-8111-111111111111";
    const sessionsDir = path.join(tmpDir, ".rpa", "sessions");
    fs.mkdirSync(sessionsDir, { recursive: true });
    const file = path.join(sessionsDir, `${sessionId}.json`);
    fs.writeFileSync(file, "{}", "utf8");

    const resolved = await resolveQuoteSessionStoragePath(sessionId);
    expect(resolved).toBe(file);
  });
});
