// lib/env-file.ts
//
// Minimal .env reader/writer. Used only by server-side, Node-runtime code
// (the install wizard's API routes, and the seed script) — never imported
// from middleware or client components, since it touches the filesystem.

import fs from "fs";
import path from "path";

const ENV_PATH = path.join(process.cwd(), ".env");

/**
 * Parses a .env file's raw text into an ordered list of lines, distinguishing
 * KEY=value lines from comments/blank lines, so we can rewrite it without
 * destroying formatting or unrelated keys.
 */
function parseLines(raw: string): string[] {
  return raw.split(/\r?\n/);
}

function isKeyLine(line: string, key: string): boolean {
  const trimmed = line.trimStart();
  return trimmed.startsWith(`${key}=`);
}

/**
 * Reads the current .env file into a plain key/value map. Returns an empty
 * object if the file doesn't exist yet (first-ever boot).
 */
export function readEnvFile(): Record<string, string> {
  if (!fs.existsSync(ENV_PATH)) return {};

  const raw = fs.readFileSync(ENV_PATH, "utf8");
  const result: Record<string, string> = {};

  for (const line of parseLines(raw)) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith("#")) continue;
    const eqIndex = trimmed.indexOf("=");
    if (eqIndex === -1) continue;
    const key = trimmed.slice(0, eqIndex).trim();
    let value = trimmed.slice(eqIndex + 1).trim();
    // Strip surrounding quotes if present
    if (
      (value.startsWith('"') && value.endsWith('"')) ||
      (value.startsWith("'") && value.endsWith("'"))
    ) {
      value = value.slice(1, -1);
    }
    result[key] = value;
  }

  return result;
}

/**
 * Writes/updates one or more keys in .env, preserving every other existing
 * line (comments, unrelated keys, ordering) untouched. Creates the file if
 * it doesn't exist. Values are always written double-quoted.
 */
export function updateEnvFile(updates: Record<string, string>): void {
  const existingRaw = fs.existsSync(ENV_PATH) ? fs.readFileSync(ENV_PATH, "utf8") : "";
  const lines = existingRaw ? parseLines(existingRaw) : [];

  const remainingKeys = new Set(Object.keys(updates));

  const updatedLines = lines.map((line) => {
    for (const key of remainingKeys) {
      if (isKeyLine(line, key)) {
        remainingKeys.delete(key);
        return `${key}="${updates[key]}"`;
      }
    }
    return line;
  });

  // Any keys that didn't already exist in the file get appended.
  if (remainingKeys.size > 0) {
    if (updatedLines.length > 0 && updatedLines[updatedLines.length - 1].trim() !== "") {
      updatedLines.push("");
    }
    for (const key of remainingKeys) {
      updatedLines.push(`${key}="${updates[key]}"`);
    }
  }

  fs.writeFileSync(ENV_PATH, updatedLines.join("\n"), { encoding: "utf8", mode: 0o600 });
}
