import { FIELDS, isFieldVisible, SECTIONS, UI_ONLY_KEYS } from "./fields";
import type { Values } from "./types";

/** Initial values: every field's defaultValue (empty string when none). */
export function defaultValues(): Values {
  const v: Values = {};
  for (const f of FIELDS) v[f.key] = f.defaultValue ?? "";
  return v;
}

const HEADER = [
  "# Self-hosted Solana Developer Platform — generated by the configurator.",
  "# Place next to compose.yml, then: docker compose up -d",
  "",
].join("\n");

/** Build a complete, bootable .env from form values, grouped by section with comments. */
export function generateEnv(values: Values): string {
  const lines: string[] = [HEADER];

  for (const section of SECTIONS) {
    const fields = FIELDS.filter(
      (f) =>
        f.section === section.id &&
        !UI_ONLY_KEYS.has(f.key) &&
        (f.derive || f.alwaysEmit ? true : isFieldVisible(f, values))
    );

    const sectionLines: string[] = [];
    for (const f of fields) {
      const raw = f.derive ? f.derive(values) : (values[f.key] ?? f.defaultValue ?? "");
      // Trim and strip CR/LF/NUL so the emitted value matches what validation
      // checked (which trims) and can never inject additional .env lines, even
      // when fed by an unvalidated caller.
      const value = raw.trim().replace(/[\r\n\0]/g, "");
      // Omit empty optional fields entirely: an empty assignment (KEY=) defeats
      // the runtime's `env.KEY ?? default` fallbacks (?? only triggers on
      // undefined), so leaving the key out lets those defaults apply. Required
      // fields are non-empty after validation and so are always emitted.
      if (value === "") continue;
      sectionLines.push(`${f.key}=${value}`);
    }

    if (sectionLines.length === 0) continue;
    lines.push(`# ${section.comment}`, ...sectionLines, "");
  }

  return `${lines.join("\n").trimEnd()}\n`;
}
