/**
 * wrangler.toml generator tests.
 *
 * These tests focus on byte-level output correctness. Wrangler itself
 * validates the result during `wrangler dev` / `wrangler deploy`, which
 * happens in integration tests outside the unit layer.
 */

import { describe, it, expect } from "bun:test";
import { generateWranglerConfig } from "../src/workers/wrangler-config";

describe("generateWranglerConfig", () => {
  it("emits a minimal valid config with just projectName", () => {
    const toml = generateWranglerConfig({ projectName: "my-app" });

    expect(toml).toContain(`name = "my-app"`);
    expect(toml).toContain(`main = ".mandu/workers/worker.js"`);
    expect(toml).toContain(`compatibility_date = "2025-09-23"`);
    expect(toml).toContain(`compatibility_flags = ["nodejs_compat"]`);
    expect(toml.endsWith("\n")).toBe(true);
  });

  it("overrides main, compatibility_date, and flags when provided", () => {
    const toml = generateWranglerConfig({
      projectName: "app",
      main: "./build/index.mjs",
      compatibilityDate: "2026-01-01",
      compatibilityFlags: ["nodejs_compat", "streams_enable_constructors"],
    });

    expect(toml).toContain(`main = "./build/index.mjs"`);
    expect(toml).toContain(`compatibility_date = "2026-01-01"`);
    expect(toml).toContain(
      `compatibility_flags = ["nodejs_compat","streams_enable_constructors"]`
    );
  });

  it("emits [assets] block when assetsDir is set (with default ASSETS binding)", () => {
    const toml = generateWranglerConfig({
      projectName: "app",
      assetsDir: "public",
    });

    expect(toml).toContain("[assets]");
    expect(toml).toContain(`directory = "public"`);
    expect(toml).toContain(`binding = "ASSETS"`);
  });

  it("honors a custom assets binding name", () => {
    const toml = generateWranglerConfig({
      projectName: "app",
      assetsDir: "public",
      assetsBinding: "STATIC",
    });

    expect(toml).toContain(`binding = "STATIC"`);
  });

  it("emits [vars] block with JSON-quoted values", () => {
    const toml = generateWranglerConfig({
      projectName: "app",
      vars: {
        API_URL: "https://api.example.com",
        FEATURE_FLAG: "true",
      },
    });

    expect(toml).toContain("[vars]");
    expect(toml).toContain(`API_URL = "https://api.example.com"`);
    expect(toml).toContain(`FEATURE_FLAG = "true"`);
  });

  it("enforces UPPER_SNAKE_CASE for var names", () => {
    expect(() =>
      generateWranglerConfig({
        projectName: "app",
        vars: { "kebab-case": "no" },
      })
    ).toThrow(/UPPER_SNAKE_CASE/);

    expect(() =>
      generateWranglerConfig({
        projectName: "app",
        vars: { camelCase: "no" },
      })
    ).toThrow(/UPPER_SNAKE_CASE/);
  });

  it("emits [[routes]] entries with pattern + optional zone", () => {
    const toml = generateWranglerConfig({
      projectName: "app",
      routes: [
        { pattern: "example.com/*", zoneName: "example.com" },
        { pattern: "api.example.com/v1/*", custom_domain: true },
      ],
    });

    expect(toml).toContain("[[routes]]");
    expect(toml).toContain(`pattern = "example.com/*"`);
    expect(toml).toContain(`zone_name = "example.com"`);
    expect(toml).toContain(`pattern = "api.example.com/v1/*"`);
    expect(toml).toContain(`custom_domain = true`);
  });

  it("emits [triggers] crons array when crons are set", () => {
    const toml = generateWranglerConfig({
      projectName: "app",
      crons: ["0 */5 * * *", "@daily"],
    });

    expect(toml).toContain("[triggers]");
    expect(toml).toContain(`crons = ["0 */5 * * *","@daily"]`);
  });

  it("emits [observability] block when observability is enabled", () => {
    const toml = generateWranglerConfig({
      projectName: "app",
      observability: true,
    });

    expect(toml).toContain("[observability]");
    expect(toml).toContain("enabled = true");
  });

  it("rejects invalid project names (security / wrangler compatibility)", () => {
    expect(() => generateWranglerConfig({ projectName: "" })).toThrow(
      /projectName is required/
    );
    expect(() =>
      generateWranglerConfig({ projectName: "UPPERCASE" })
    ).toThrow(/must match/);
    expect(() =>
      generateWranglerConfig({ projectName: "spaces not allowed" })
    ).toThrow(/must match/);
    expect(() =>
      generateWranglerConfig({ projectName: "../escape" })
    ).toThrow(/must match/);
  });

  it("uses the leading comment header that wrangler tooling expects", () => {
    const toml = generateWranglerConfig({ projectName: "x" });
    // Starts with `# Generated by …` — Wrangler ignores comments but humans
    // rely on the provenance marker.
    expect(toml.startsWith("# Generated by mandu build --target=workers")).toBe(true);
  });
});
