import { appendFile, mkdir, readFile } from "node:fs/promises";
import { dirname, join } from "node:path";

export type WaitlistFileRow = {
  id: string;
  email: string;
  createdAt: Date;
  locale: string;
  /** `ios` | `android`; puste dla starych wierszy (3 kolumny). */
  platform: string;
};

function getFilePath(): string {
  const fromEnv = process.env.WAITLIST_FILE_PATH?.trim();
  if (fromEnv) return fromEnv;
  return join(process.cwd(), "data", "waitlist.txt");
}

/** Kolejka zapisów — unika wyścigów przy równoległych POST. */
let writeQueue = Promise.resolve();

function enqueueWrite<T>(task: () => Promise<T>): Promise<T> {
  const run = writeQueue.then(() => task());
  writeQueue = run.then(
    () => undefined,
    () => undefined,
  );
  return run;
}

/**
 * Odczyt istniejących adresów (małe litery) — do wykrywania duplikatów.
 */
async function loadEmailsLower(filePath: string): Promise<Set<string>> {
  const set = new Set<string>();
  let raw: string;
  try {
    raw = await readFile(filePath, "utf8");
  } catch (e: unknown) {
    if ((e as NodeJS.ErrnoException).code === "ENOENT") return set;
    throw e;
  }
  for (const line of raw.split("\n")) {
    if (!line.trim()) continue;
    const parts = line.split("\t");
    const email = parts[1]?.trim().toLowerCase();
    if (email) set.add(email);
  }
  return set;
}

export async function appendWaitlistEntry(
  email: string,
  locale: string,
  platform: "ios" | "android",
): Promise<"created" | "duplicate"> {
  const normalized = email.trim().toLowerCase();
  const filePath = getFilePath();

  return enqueueWrite(async () => {
    await mkdir(dirname(filePath), { recursive: true });
    const existing = await loadEmailsLower(filePath);
    if (existing.has(normalized)) return "duplicate";

    const iso = new Date().toISOString();
    const loc = locale.trim() || "?";
    const line = `${iso}\t${normalized}\t${loc}\t${platform}\n`;
    await appendFile(filePath, line, "utf8");
    return "created";
  });
}

export async function readWaitlistEntries(): Promise<WaitlistFileRow[]> {
  const filePath = getFilePath();
  let raw: string;
  try {
    raw = await readFile(filePath, "utf8");
  } catch (e: unknown) {
    if ((e as NodeJS.ErrnoException).code === "ENOENT") return [];
    throw e;
  }

  const rows: WaitlistFileRow[] = [];
  let n = 0;
  for (const line of raw.split("\n")) {
    if (!line.trim()) continue;
    const parts = line.split("\t");
    const ts = parts[0]?.trim() ?? "";
    const em = parts[1]?.trim() ?? "";
    const loc = parts[2]?.trim() ?? "";
    const plat = parts[3]?.trim() ?? "";
    if (!em) continue;
    const createdAt = new Date(ts);
    rows.push({
      id: `w-${n++}`,
      email: em,
      createdAt: Number.isNaN(createdAt.getTime()) ? new Date(0) : createdAt,
      locale: loc,
      platform: plat,
    });
  }
  return rows.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
}
