/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

pub use maka_agent_facts::model::assembly::StepBuilder;

#[cfg(test)]
mod tests {
    use super::*;
    use maka_agent_facts::model::ModelEvent;
    use maka_agent_facts::model::ModelFinishReason;
    use maka_agent_facts::model::ModelPart;
    use maka_agent_facts::model::ModelUsage;
    use maka_agent_facts::model::TextKind;
    use serde_json::json;

    #[test]
    fn interleaved_parts_preserve_metadata_and_require_complete_streams() {
        let events = [
            ModelEvent::PartStarted {
                id: "r".into(),
                text_kind: TextKind::Thinking,
                provider_options: Some(json!({"anthropic":{"signature":"initial","other":1}})),
            },
            ModelEvent::PartStarted {
                id: "t".into(),
                text_kind: TextKind::Text,
                provider_options: None,
            },
            ModelEvent::PartDelta {
                id: "r".into(),
                text: "think".into(),
                provider_options: None,
            },
            ModelEvent::PartDelta {
                id: "t".into(),
                text: "answer".into(),
                provider_options: None,
            },
            ModelEvent::PartFinished {
                id: "r".into(),
                provider_options: Some(json!({"anthropic":{"signature":"signed"}})),
            },
            ModelEvent::PartFinished {
                id: "t".into(),
                provider_options: Some(json!({"openai":{"itemId":"item"}})),
            },
            ModelEvent::Finished {
                reason: ModelFinishReason::Stop,
                usage: ModelUsage {
                    input_tokens: Some(3),
                    output_tokens: Some(4),
                    reasoning_tokens: Some(2),
                    ..Default::default()
                },
                provider_options: None,
            },
        ];
        for length in [4, 6, 7] {
            let mut builder = StepBuilder::default();
            for event in &events[..length] {
                builder.push(event.clone()).unwrap();
            }
            let result = builder.finish();
            assert_eq!(result.is_ok(), length == 7);
            if let Ok(step) = result {
                assert_eq!(
                    step.parts,
                    vec![
                        ModelPart::Text {
                            text_kind: TextKind::Thinking,
                            text: "think".into(),
                            provider_options: Some(
                                json!({"anthropic":{"signature":"signed","other":1}})
                            )
                        },
                        ModelPart::Text {
                            text_kind: TextKind::Text,
                            text: "answer".into(),
                            provider_options: Some(json!({"openai":{"itemId":"item"}}))
                        },
                    ]
                );
                assert_eq!(step.usage.reasoning_tokens, Some(2));
            }
        }
        for already_finished in [false, true] {
            let mut builder = StepBuilder::default();
            let finish = ModelEvent::Finished {
                reason: ModelFinishReason::Stop,
                usage: ModelUsage::default(),
                provider_options: None,
            };
            if already_finished {
                builder.push(finish.clone()).unwrap();
            }
            assert!(
                builder
                    .push(ModelEvent::PartFinished {
                        id: "unknown".into(),
                        provider_options: None,
                    })
                    .is_err()
            );
            assert!(builder.push(finish).is_err());
            assert!(builder.finish().is_err());
        }
        for reason in ["content-filter", "error", "unknown"] {
            assert!(serde_json::from_value::<ModelFinishReason>(json!(reason)).is_err());
        }
        for (reason, wire) in [
            (ModelFinishReason::Stop, "stop"),
            (ModelFinishReason::ToolCalls, "tool-calls"),
            (ModelFinishReason::Length, "length"),
        ] {
            assert_eq!(serde_json::to_value(reason).unwrap(), json!(wire));
            assert_eq!(
                serde_json::from_value::<ModelFinishReason>(json!(wire)).unwrap(),
                reason
            );
            let finish = ModelEvent::Finished {
                reason,
                usage: ModelUsage {
                    input_tokens: Some(3),
                    output_tokens: Some(8),
                    ..Default::default()
                },
                provider_options: None,
            };
            let mut builder = StepBuilder::default();
            builder.push(finish).unwrap();
            let step = builder.finish().unwrap();
            assert_eq!(step.finish_reason, reason);
            assert_eq!(step.usage.output_tokens, Some(8));
        }
    }
}
