// Request Tracing Demo
// Run with: cargo run --example trace_id_demo --features actix

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

use actix_web::{App, HttpServer, Responder, get, web};
use anycms_core::{ApiResult, FieldError};
use serde::Serialize;
use std::sync::atomic::{AtomicU64, Ordering};

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

static COUNTER: AtomicU64 = AtomicU64::new(1);

fn generate_trace_id() -> String {
    let ts = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_millis();
    let seq = COUNTER.fetch_add(1, Ordering::Relaxed);
    format!("req-{}-{}", ts, seq)
}

// 模拟中间件：为每个请求生成 trace_id
// 实际项目中可以用 actix-web middleware 自动注入
fn attach_trace_id<T>(result: ApiResult<T>) -> ApiResult<T> {
    result.with_trace_id(generate_trace_id())
}

#[get("/")]
async fn index() -> impl Responder {
    attach_trace_id(ApiResult::<()>::ok().with_message("服务运行正常"))
}

#[get("/users/{id}")]
async fn get_user(path: web::Path<u32>) -> impl Responder {
    let user_id = path.into_inner();

    match user_id {
        1 => {
            let user = User {
                id: 1,
                name: "张三".to_string(),
            };
            attach_trace_id(ApiResult::value(user))
        }
        _ => attach_trace_id(ApiResult::<User>::fail("用户不存在").with_code(404)),
    }
}

#[get("/validate")]
async fn validate_demo() -> impl Responder {
    // 模拟表单验证失败，带 trace_id
    attach_trace_id(ApiResult::<()>::validation_errors(vec![
        FieldError::new("email", "邮箱格式不正确"),
        FieldError::new("name", "用户名不能为空"),
    ]))
}

#[get("/error")]
async fn error_demo() -> ApiResult<()> {
    // 模拟内部错误，带 trace_id 方便排查
    attach_trace_id(ApiResult::fail("数据库连接超时").with_code(500))
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    println!("Starting Trace ID Demo Server...");
    println!();
    println!("Endpoints:");
    println!("  GET  /            - Success with trace ID");
    println!("  GET  /users/1     - Found user with trace ID");
    println!("  GET  /users/999   - Not found with trace ID");
    println!("  GET  /validate    - Validation errors with trace ID");
    println!("  GET  /error       - Internal error with trace ID");
    println!();
    println!("Try:");
    println!("  curl http://localhost:8080/users/1");
    println!("  curl http://localhost:8080/users/999");
    println!("  curl http://localhost:8080/validate");

    HttpServer::new(|| {
        App::new()
            .service(index)
            .service(get_user)
            .service(validate_demo)
            .service(error_demo)
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await?;

    Ok(())
}
