import { Type } from "@sinclair/typebox";

import type { CheckerSchemas } from "../types";

import {
  createAuthoringContentExpectationsSchema,
  createAuthoringValueExpectationSchema,
  createNormalizedContentExpectationsSchema,
  createNormalizedValueExpectationSchema,
  sizeSchema,
  stringMapSchema,
} from "../../schema/fragments";

export const commandCheckerSchemas: CheckerSchemas = {
  authoring: {
    config: createCommandConfigSchema(),
    expect: createCommandExpectSchema("authoring"),
  },
  normalized: {
    config: createCommandConfigSchema(),
    expect: createCommandExpectSchema("normalized"),
  },
};

function createCommandConfigSchema() {
  return Type.Object(
    {
      args: Type.Optional(Type.Array(Type.String())),
      cwd: Type.Optional(Type.String()),
      env: Type.Optional(stringMapSchema),
      exec: Type.String({ minLength: 1 }),
      maxOutputBytes: Type.Optional(sizeSchema),
    },
    { additionalProperties: false },
  );
}

function createCommandExpectSchema(kind: "authoring" | "normalized") {
  return Type.Object(
    {
      durationMs: Type.Optional(
        kind === "authoring" ? createAuthoringValueExpectationSchema() : createNormalizedValueExpectationSchema(),
      ),
      exitCode: Type.Optional(Type.Array(Type.Integer())),
      stderr: Type.Optional(
        kind === "authoring" ? createAuthoringContentExpectationsSchema() : createNormalizedContentExpectationsSchema(),
      ),
      stdout: Type.Optional(
        kind === "authoring" ? createAuthoringContentExpectationsSchema() : createNormalizedContentExpectationsSchema(),
      ),
    },
    { additionalProperties: false },
  );
}
