#![cfg(feature = "tracing")]

use anycms_core::{ApiResult, ApiResultTracing};
use serde::Serialize;

#[derive(Serialize)]
struct User {
    id: u32,
    name: String,
}

#[test]
fn test_tracing_success_no_log() {
    // Success responses should return self unchanged with no logging side-effects
    let user = User {
        id: 1,
        name: "Alice".to_string(),
    };
    let result: ApiResult<User> = ApiResult::value(user);
    let traced = result.with_tracing();

    assert!(traced.success);
    assert!(traced.data.is_some());
    assert_eq!(traced.code, None);
}

#[test]
fn test_tracing_client_error_warn() {
    // 4xx errors should return self unchanged (would log at WARN in real usage)
    let result: ApiResult<User> = ApiResult::fail("bad request").with_code(400);
    let traced = result.with_tracing();

    assert!(!traced.success);
    assert_eq!(traced.code, Some(400));
    assert_eq!(traced.message.as_deref(), Some("bad request"));
}

#[test]
fn test_tracing_server_error_error_level() {
    // 5xx errors should return self unchanged (would log at ERROR in real usage)
    let result: ApiResult<User> = ApiResult::fail("internal broken").with_code(500);
    let traced = result.with_tracing();

    assert!(!traced.success);
    assert_eq!(traced.code, Some(500));
    assert_eq!(traced.message.as_deref(), Some("internal broken"));
}

#[test]
fn test_tracing_with_trace_id() {
    // Errors with trace_id should preserve it through with_tracing()
    let result: ApiResult<User> = ApiResult::fail("something went wrong")
        .with_code(500)
        .with_trace_id("req-abc-123");
    let traced = result.with_tracing();

    assert!(!traced.success);
    assert_eq!(traced.code, Some(500));
    assert_eq!(traced.trace_id.as_deref(), Some("req-abc-123"));
}

#[test]
fn test_tracing_preserves_all_fields() {
    // Ensure with_tracing() does not mutate any field
    let result: ApiResult<User> = ApiResult::fail("fail")
        .with_code(422)
        .with_trace_id("trace-001")
        .with_biz_code(10001)
        .with_current_timestamp();
    let ts = result.timestamp;

    let traced = result.with_tracing();

    assert_eq!(traced.code, Some(422));
    assert_eq!(traced.trace_id.as_deref(), Some("trace-001"));
    assert_eq!(traced.biz_code, Some(10001));
    assert_eq!(traced.timestamp, ts);
    assert_eq!(traced.message.as_deref(), Some("fail"));
}
