import { Type, type Static } from "@sinclair/typebox";
import { Value } from "@sinclair/typebox/value";

const eventBase = {
  entity_ref: Type.String({ maxLength: 160, pattern: "^[a-z][a-z0-9_]*:[A-Za-z0-9_-]+$" }),
  event_id: Type.Integer({ minimum: 0 }),
  occurred_at: Type.String({ pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\\.[0-9]{3})?Z$" }),
};

export const StateSseEventSchema = Type.Object(
  {
    ...eventBase,
    event_type: Type.String({ maxLength: 80, pattern: "^(?!model_config_changed$|model_runtime_changed$)[a-z][a-z0-9_]+$" }),
    state_version: Type.Integer({ minimum: 0 }),
  },
  { additionalProperties: false, $id: "StateSseEvent" },
);
export const ModelConfigSseEventSchema = Type.Object(
  {
    ...eventBase,
    config_set_version: Type.Integer({ minimum: 0 }),
    event_type: Type.Literal("model_config_changed"),
  },
  { additionalProperties: false, $id: "ModelConfigSseEvent" },
);
export const ModelRuntimeSseEventSchema = Type.Object(
  {
    ...eventBase,
    event_type: Type.Literal("model_runtime_changed"),
    runtime_availability_version: Type.Integer({ minimum: 0 }),
  },
  { additionalProperties: false, $id: "ModelRuntimeSseEvent" },
);
export const SseEventSchema = Type.Union(
  [StateSseEventSchema, ModelConfigSseEventSchema, ModelRuntimeSseEventSchema],
  { $id: "SseEvent" },
);

export type SseEvent = Static<typeof SseEventSchema>;

export function isSseEvent(value: unknown): value is SseEvent {
  return Value.Check(SseEventSchema, value);
}
