///|
pub(all) enum PromptRole {
  System
  User
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct PromptSection {
  title : String
  body : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct PromptMessage {
  role : PromptRole
  content : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct PromptPacket {
  stage : @routine.ModelStage
  schema_id : String
  messages : Array[PromptMessage]
  sections : Array[PromptSection]
  required_tools : Array[String]
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn prompt_section(title : String, body : String) -> PromptSection {
  { title, body }
}

///|
pub fn prompt_message(role : PromptRole, content : String) -> PromptMessage {
  { role, content }
}

///|
pub fn prompt_packet(
  stage : @routine.ModelStage,
  schema_id : String,
  sections : Array[PromptSection],
  required_tools : Array[String],
) -> PromptPacket {
  {
    stage,
    schema_id,
    sections,
    required_tools,
    messages: [
      prompt_message(
        System,
        "You are Moonfish, a bounded price-action analysis routine. Return bare JSON matching the requested schema.",
      ),
      prompt_message(User, render_sections(sections)),
    ],
  }
}

///|
pub fn render_sections(sections : Array[PromptSection]) -> String {
  sections
  .map(fn(section) { "## \{section.title}\n\{section.body}" })
  .join("\n\n")
}

///|
pub fn PromptPacket::text(self : PromptPacket) -> String {
  self.messages.map(fn(message) { message.content }).join("\n\n")
}