// Direct port of https://github.com/openai/codex/blob/f201c30c52a35f819262865a53df94b6f4ea7a50/sdk/typescript/src/outputSchemaFile.ts

///| Stores the optional schema path and the directory needed for cleanup.

///| Upstream: https://github.com/openai/codex/blob/f201c30c52a35f819262865a53df94b6f4ea7a50/sdk/typescript/src/outputSchemaFile.ts#L5-L8

///|
/// Type difference: MoonBit represents the cleanup closure as a method and retains its directory as private state.
priv struct OutputSchemaFile_ {
  schema_path : @path.Path?
  schema_directory : String?
}

///| Creates the temporary schema file and removes it if writing fails.

///| Upstream: https://github.com/openai/codex/blob/f201c30c52a35f819262865a53df94b6f4ea7a50/sdk/typescript/src/outputSchemaFile.ts#L10-L36

///|
/// Type difference: Json replaces TypeScript unknown and Path replaces filesystem strings.
async fn create_output_schema_file_(schema : Json?) -> OutputSchemaFile_ {
  match schema {
    None => { schema_path: None, schema_directory: None }
    Some(schema) => {
      guard schema is Json::Object(_) else {
        raise InvalidOutputSchema(
          message="output_schema must be a plain JSON object",
        )
      }
      let schema_directory = @fs.tmpdir(prefix="codex-output-schema-")
      let schema_path = @path.Path(schema_directory)
        |> @path.Path::join(@path.Path("schema.json"))
      try {
        @fs.write_file(
          "\{schema_path}",
          schema.stringify(),
          create_mode=CreateOrTruncate,
        )
        {
          schema_path: Some(schema_path),
          schema_directory: Some(schema_directory),
        }
      } catch {
        error => {
          @fs.rmdir(schema_directory, recursive=true) catch {
            _ => ()
          }
          raise error
        }
      }
    }
  }
}

///| Removes the temporary schema directory while suppressing cleanup failures.

///| Upstream cleanup closure: https://github.com/openai/codex/blob/f201c30c52a35f819262865a53df94b6f4ea7a50/sdk/typescript/src/outputSchemaFile.ts#L21-L27

///|
/// Type difference: this method replaces the upstream cleanup closure stored in OutputSchemaFile_.
async fn OutputSchemaFile_::cleanup_(self : OutputSchemaFile_) -> Unit {
  if self.schema_directory is Some(directory) {
    @fs.rmdir(directory, recursive=true) catch {
      _ => ()
    }
  }
}