import * as DateTime from "effect/DateTime"
import { Schema } from "effect"
import { NonNegativeInt } from "@/util/schema"
import { Base, SessionEventID, type BaseInput } from "./session-event-base"

export namespace Step {
  export class Started extends Schema.Class<Started>("Session.Event.Step.Started")({
    ...Base,
    type: Schema.Literal("step.started"),
    model: Schema.Struct({
      id: Schema.String,
      providerID: Schema.String,
      variant: Schema.String.pipe(Schema.optional),
    }),
  }) {
    static create(input: BaseInput & { model: { id: string; providerID: string; variant?: string } }) {
      return new Started({
        id: input.id ?? SessionEventID.create(),
        type: "step.started",
        timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()),
        metadata: input.metadata,
        model: input.model,
      })
    }
  }

  export class Ended extends Schema.Class<Ended>("Session.Event.Step.Ended")({
    ...Base,
    type: Schema.Literal("step.ended"),
    reason: Schema.String,
    cost: Schema.Finite,
    tokens: Schema.Struct({
      input: NonNegativeInt,
      output: NonNegativeInt,
      reasoning: NonNegativeInt,
      cache: Schema.Struct({ read: NonNegativeInt, write: NonNegativeInt }),
    }),
  }) {
    static create(input: BaseInput & { reason: string; cost: number; tokens: Ended["tokens"] }) {
      return new Ended({
        id: input.id ?? SessionEventID.create(),
        type: "step.ended",
        timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()),
        metadata: input.metadata,
        reason: input.reason,
        cost: input.cost,
        tokens: input.tokens,
      })
    }
  }
}
