// DefaultResult<T> demo example
//
// DefaultResult<T> = Result<T, Box<dyn Error>>
//
// This matches the actual handler pattern used across the anycms ecosystem.
// Handlers always return Ok(ApiResult::...) — the Err branch is never used
// because ApiResult itself encodes success/failure in its `success` field.
//
// Run with: cargo run --example default_result_demo --features actix

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

use actix_web::{App, HttpServer, Responder, get, post, web};
use anycms_core::{ApiResult, DefaultResult, FieldError, ResultPagination};
use serde::{Deserialize, Serialize};

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

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

// ── Handler examples using DefaultResult<T> ──

/// Simple health check — returns empty success
#[get("/health")]
async fn health() -> DefaultResult<impl Responder> {
    Ok(ApiResult::<()>::ok().with_message("Service is healthy"))
}

/// List users with pagination
#[get("/users")]
async fn list_users() -> DefaultResult<impl Responder> {
    let users = vec![
        User { id: 1, name: "Alice".into(), email: "alice@example.com".into() },
        User { id: 2, name: "Bob".into(), email: "bob@example.com".into() },
    ];
    let pagination = ResultPagination::new(100, 1, 10);

    Ok(ApiResult::list(users)
        .with_pagination(pagination)
        .with_message("Users retrieved successfully"))
}

/// Get single user — success or 404
#[get("/users/{id}")]
async fn get_user(path: web::Path<u32>) -> DefaultResult<impl Responder> {
    let user_id = path.into_inner();

    if user_id == 1 {
        Ok(ApiResult::value(User {
            id: 1,
            name: "Alice".into(),
            email: "alice@example.com".into(),
        }))
    } else {
        Ok(ApiResult::<User>::fail("User not found").with_code(404))
    }
}

/// Create user with validation
#[post("/users")]
async fn create_user(body: web::Json<CreateUserRequest>) -> DefaultResult<impl Responder> {
    // Manual validation
    let mut errors = Vec::new();
    if body.name.is_empty() {
        errors.push(FieldError::new("name", "Name is required"));
    }
    if !body.email.contains('@') {
        errors.push(FieldError::new("email", "Invalid email format"));
    }
    if !errors.is_empty() {
        return Ok(ApiResult::validation_errors(errors));
    }

    let user = User {
        id: 999,
        name: body.name.clone(),
        email: body.email.clone(),
    };

    Ok(ApiResult::value(user)
        .with_message("User created successfully")
        .with_biz_code(0))
}

/// Error with business code
#[get("/error/biz")]
async fn business_error() -> DefaultResult<impl Responder> {
    Ok(ApiResult::<User>::fail("User quota exceeded")
        .with_code(403)
        .with_biz_code(30001))
}

/// Complex response with extra metadata
#[get("/stats")]
async fn stats() -> DefaultResult<impl Responder> {
    Ok(ApiResult::<()>::ok()
        .with_message("System stats")
        .with_extra("total_users", serde_json::json!(1024))
        .with_extra("active_users", serde_json::json!(512))
        .with_extra("version", serde_json::json!("1.0.0")))
}

#[actix_web::main]
async fn main() -> anyhow::Result<()> {
    println!("=== DefaultResult<T> Demo ===\n");
    println!("DefaultResult<T> = Result<T, Box<dyn Error>>");
    println!("Handlers always return Ok(ApiResult::...) — the Err branch is never used.\n");
    println!("Endpoints:");
    println!("  GET  /health       - Empty success with message");
    println!("  GET  /users        - List with pagination");
    println!("  GET  /users/1      - Single value (found)");
    println!("  GET  /users/999    - Error response (not found)");
    println!("  POST /users        - Create with validation");
    println!("  GET  /error/biz    - Business error with biz_code");
    println!("  GET  /stats        - Success with extra metadata\n");
    println!("Try:");
    println!("  curl http://localhost:8082/health");
    println!("  curl http://localhost:8082/users");
    println!("  curl http://localhost:8082/users/999");
    println!("  curl -X POST http://localhost:8082/users -H 'Content-Type: application/json' -d '{{\"name\":\"\",\"email\":\"bad\"}}'");
    println!("  curl http://localhost:8082/error/biz");
    println!("  curl http://localhost:8082/stats");

    HttpServer::new(|| {
        App::new()
            .service(health)
            .service(list_users)
            .service(get_user)
            .service(create_user)
            .service(business_error)
            .service(stats)
    })
    .bind("127.0.0.1:8082")?
    .run()
    .await?;

    Ok(())
}
