// Axum demo example
// Run with: cargo run --example axum_demo --features axum

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

use anycms_core::{ApiResult, ResultPagination};
use axum::{
    Router,
    extract::{Json, Path},
    routing::get,
};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;

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

#[derive(Debug, Serialize, Deserialize)]
struct CreateUserRequest {
    name: String,
    email: String,
}

// Mock user data
async fn get_users() -> Vec<User> {
    vec![
        User {
            id: 1,
            name: "张三".to_string(),
            email: "zhangsan@example.com".to_string(),
        },
        User {
            id: 2,
            name: "李四".to_string(),
            email: "lisi@example.com".to_string(),
        },
        User {
            id: 3,
            name: "王五".to_string(),
            email: "wangwu@example.com".to_string(),
        },
    ]
}

async fn get_user_by_id(id: u32) -> Option<User> {
    let users = get_users().await;
    users.into_iter().find(|u| u.id == id)
}

async fn index() -> ApiResult<()> {
    ApiResult::ok()
}

async fn list_users() -> ApiResult<User> {
    let users = get_users().await;
    let pagination = ResultPagination::new(100, 1, 10);

    ApiResult::list(users)
        .with_pagination(pagination)
        .with_extra("total_count", serde_json::json!(100))
        .with_extra("has_more", serde_json::json!(true))
}

async fn get_user(Path(id): Path<u32>) -> ApiResult<User> {
    match get_user_by_id(id).await {
        Some(user) => ApiResult::value(user),
        None => ApiResult::fail("用户不存在"),
    }
}

async fn create_user(Json(user_data): Json<CreateUserRequest>) -> ApiResult<User> {
    let new_user = User {
        id: 999,
        name: user_data.name.clone(),
        email: user_data.email.clone(),
    };

    ApiResult::value(new_user)
        .with_extra("created_at", serde_json::json!("2024-01-01T00:00:00Z"))
        .with_extra("status", serde_json::json!("active"))
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    println!("🚀 Starting Axum demo server...");
    println!("📝 Available endpoints:");
    println!("  GET  /              - Basic success response");
    println!("  GET  /users         - User list with pagination");
    println!("  GET  /users/1       - Get single user");
    println!("  POST /users         - Create user");

    let app = Router::new()
        .route("/", get(index))
        .route("/users", get(list_users).post(create_user))
        .route("/users/{id}", get(get_user));

    let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
    let listener = tokio::net::TcpListener::bind(addr).await?;

    println!("✅ Server listening on http://127.0.0.1:8080");
    axum::serve(listener, app).await?;

    Ok(())
}
