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

export namespace Tool {
  export namespace Input {
    export class Started extends Schema.Class<Started>("Session.Event.Tool.Input.Started")({
      ...Base,
      callID: Schema.String,
      name: Schema.String,
      type: Schema.Literal("tool.input.started"),
    }) {
      static create(input: BaseInput & { callID: string; name: string }) {
        return new Started({ id: input.id ?? SessionEventID.create(), type: "tool.input.started", timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()), metadata: input.metadata, callID: input.callID, name: input.name })
      }
    }

    export class Delta extends Schema.Class<Delta>("Session.Event.Tool.Input.Delta")({
      ...Base,
      callID: Schema.String,
      type: Schema.Literal("tool.input.delta"),
      delta: Schema.String,
    }) {
      static create(input: BaseInput & { callID: string; delta: string }) {
        return new Delta({ id: input.id ?? SessionEventID.create(), type: "tool.input.delta", timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()), metadata: input.metadata, callID: input.callID, delta: input.delta })
      }
    }

    export class Ended extends Schema.Class<Ended>("Session.Event.Tool.Input.Ended")({
      ...Base,
      callID: Schema.String,
      type: Schema.Literal("tool.input.ended"),
      text: Schema.String,
    }) {
      static create(input: BaseInput & { callID: string; text: string }) {
        return new Ended({ id: input.id ?? SessionEventID.create(), type: "tool.input.ended", timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()), metadata: input.metadata, callID: input.callID, text: input.text })
      }
    }
  }

  export class Called extends Schema.Class<Called>("Session.Event.Tool.Called")({
    ...Base,
    type: Schema.Literal("tool.called"),
    callID: Schema.String,
    tool: Schema.String,
    input: Schema.Record(Schema.String, Schema.Unknown),
    provider: Schema.Struct({
      executed: Schema.Boolean,
      metadata: Schema.Record(Schema.String, Schema.Unknown).pipe(Schema.optional),
    }),
  }) {
    static create(input: BaseInput & { callID: string; tool: string; input: Record<string, unknown>; provider: Called["provider"] }) {
      return new Called({ id: input.id ?? SessionEventID.create(), type: "tool.called", timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()), metadata: input.metadata, callID: input.callID, tool: input.tool, input: input.input, provider: input.provider })
    }
  }

  export class Success extends Schema.Class<Success>("Session.Event.Tool.Success")({
    ...Base,
    type: Schema.Literal("tool.success"),
    callID: Schema.String,
    title: Schema.String,
    output: Schema.String.pipe(Schema.optional),
    attachments: Schema.Array(FileAttachment).pipe(Schema.optional),
    provider: Schema.Struct({
      executed: Schema.Boolean,
      metadata: Schema.Record(Schema.String, Schema.Unknown).pipe(Schema.optional),
    }),
  }) {
    static create(input: BaseInput & { callID: string; title: string; output?: string; attachments?: FileAttachment[]; provider: Success["provider"] }) {
      return new Success({ id: input.id ?? SessionEventID.create(), type: "tool.success", timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()), metadata: input.metadata, callID: input.callID, title: input.title, output: input.output, attachments: input.attachments, provider: input.provider })
    }
  }

  export class Error extends Schema.Class<Error>("Session.Event.Tool.Error")({
    ...Base,
    type: Schema.Literal("tool.error"),
    callID: Schema.String,
    error: Schema.String,
    provider: Schema.Struct({
      executed: Schema.Boolean,
      metadata: Schema.Record(Schema.String, Schema.Unknown).pipe(Schema.optional),
    }),
  }) {
    static create(input: BaseInput & { callID: string; error: string; provider: Error["provider"] }) {
      return new Error({ id: input.id ?? SessionEventID.create(), type: "tool.error", timestamp: input.timestamp ?? DateTime.makeUnsafe(Date.now()), metadata: input.metadata, callID: input.callID, error: input.error, provider: input.provider })
    }
  }
}
