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

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

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

export const udpCheckerSchemas: CheckerSchemas = {
  authoring: {
    config: createUdpConfigSchema("authoring"),
    expect: createUdpExpectSchema("authoring"),
  },
  normalized: {
    config: createUdpConfigSchema("normalized"),
    expect: createUdpExpectSchema("normalized"),
  },
};

function createEncodingSchema() {
  return Type.Union([Type.Literal("text"), Type.Literal("hex"), Type.Literal("base64")]);
}

function createUdpConfigSchema(kind: "authoring" | "normalized") {
  const port = Type.Integer({ maximum: 65535, minimum: 1 });
  const encoding = createEncodingSchema();
  const responseEncoding = createEncodingSchema();
  return Type.Object(
    {
      encoding: Type.Optional(kind === "authoring" ? createAuthoringFieldSchema(encoding) : encoding),
      host: Type.String({ minLength: 1 }),
      maxResponseBytes: Type.Optional(sizeSchema),
      payload: Type.Optional(Type.String()),
      port: kind === "authoring" ? createAuthoringFieldSchema(port) : port,
      responseEncoding: Type.Optional(
        kind === "authoring" ? createAuthoringFieldSchema(responseEncoding) : responseEncoding,
      ),
    },
    { additionalProperties: false },
  );
}

function createUdpExpectSchema(kind: "authoring" | "normalized") {
  const responded = Type.Boolean();
  return Type.Object(
    {
      durationMs: Type.Optional(
        kind === "authoring" ? createAuthoringValueExpectationSchema() : createNormalizedValueExpectationSchema(),
      ),
      responded: Type.Optional(kind === "authoring" ? createAuthoringFieldSchema(responded) : responded),
      response: Type.Optional(
        kind === "authoring" ? createAuthoringContentExpectationsSchema() : createNormalizedContentExpectationsSchema(),
      ),
      responseSize: Type.Optional(
        kind === "authoring" ? createAuthoringValueExpectationSchema() : createNormalizedValueExpectationSchema(),
      ),
      sourceHost: Type.Optional(
        kind === "authoring" ? createAuthoringValueExpectationSchema() : createNormalizedValueExpectationSchema(),
      ),
      sourcePort: Type.Optional(
        kind === "authoring" ? createAuthoringValueExpectationSchema() : createNormalizedValueExpectationSchema(),
      ),
    },
    { additionalProperties: false },
  );
}
