import { describe, expect, it } from "vitest";
import {
  goService,
  nextService,
  nodeToolchain,
  schemaSql,
  seedCommand,
  seedModule,
  seededDatabaseTemplate,
  tsxService,
  verifyCommand,
  verifyModule,
} from "./index.mjs";

describe("setup helpers", () => {
  it("emits plain next start commands without an exec prefix", () => {
    const config = nextService({ port: 3000 });

    expect(config.local.start).toBe("./node_modules/.bin/next dev -p {port}");
  });

  it("emits plain tsx start commands without an exec prefix", () => {
    const config = tsxService({ port: 3000, entry: "src/server.ts" });

    expect(config.local.start).toBe("./node_modules/.bin/tsx watch src/server.ts");
  });

  it("emits plain go start commands without an exec prefix", () => {
    expect(goService({ port: 3000 }).local.start).toBe("go run ./cmd/server");
    expect(goService({ port: 3000, entrypoint: "./cmd/api" }).local.start).toBe(
      "go run ./cmd/api"
    );
    expect(goService({ port: 3000, command: "./cmd/worker" }).local.start).toBe(
      "go run ./cmd/worker"
    );
  });

  it("builds node toolchain profiles with a node kind", () => {
    expect(nodeToolchain({ node: "20.19.5", install: "download" })).toEqual({
      kind: "node",
      node: "20.19.5",
      install: "download",
    });
  });

  it("emits semantic database template steps using the underlying step shapes", () => {
    expect(schemaSql("db/schema.sql")).toEqual({
      kind: "sql-file",
      path: "db/schema.sql",
      cwd: undefined,
      inputs: undefined,
    });
    expect(seedCommand("npm run db:seed")).toEqual({
      kind: "command",
      cmd: "npm run db:seed",
      cwd: undefined,
      inputs: undefined,
    });
    expect(seedModule("scripts/seed.ts#seed")).toEqual({
      kind: "module",
      specifier: "scripts/seed.ts#seed",
      cwd: undefined,
      inputs: undefined,
    });
    expect(verifyCommand("npm run db:verify")).toEqual({
      kind: "command",
      cmd: "npm run db:verify",
      cwd: undefined,
      inputs: undefined,
    });
    expect(verifyModule("scripts/verify.ts#verify")).toEqual({
      kind: "module",
      specifier: "scripts/verify.ts#verify",
      cwd: undefined,
      inputs: undefined,
    });
  });

  it("builds a seeded database template from schema, seed, and verify intents", () => {
    expect(
      seededDatabaseTemplate({
        inputs: ["db/schema.sql", "scripts/seed.ts"],
        schema: "db/schema.sql",
        seed: seedCommand("npm run db:seed"),
        verify: verifyModule("scripts/verify.ts#verifySeed"),
      })
    ).toEqual({
      inputs: ["db/schema.sql", "scripts/seed.ts"],
      migrate: [
        {
          kind: "sql-file",
          path: "db/schema.sql",
          cwd: undefined,
          inputs: undefined,
        },
      ],
      seed: [
        {
          kind: "command",
          cmd: "npm run db:seed",
          cwd: undefined,
          inputs: undefined,
        },
      ],
      verify: [
        {
          kind: "module",
          specifier: "scripts/verify.ts#verifySeed",
          cwd: undefined,
          inputs: undefined,
        },
      ],
    });
  });

  it("prepends schema before explicit migrate steps and normalizes singletons to arrays", () => {
    expect(
      seededDatabaseTemplate({
        schema: schemaSql("db/schema.sql", { cwd: "db" }),
        migrate: seedCommand("echo migrate"),
      })
    ).toEqual({
      inputs: undefined,
      migrate: [
        {
          kind: "sql-file",
          path: "db/schema.sql",
          cwd: "db",
          inputs: undefined,
        },
        {
          kind: "command",
          cmd: "echo migrate",
          cwd: undefined,
          inputs: undefined,
        },
      ],
      seed: [],
      verify: [],
    });
  });
});
