// ErrorCode + ApiResult query methods demo
//
// Demonstrates:
// - ErrorCode enum variants and usage
// - ApiResult::is_success() / is_error() / error_code() query methods
// - Client-side deserialization of ApiResult responses
//
// Run with: cargo run --example error_code_demo

use anycms_core::{ApiResult, ErrorCode};
use serde::{Deserialize, Serialize};

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

fn main() {
    println!("=== ErrorCode & ApiResult Query Methods Demo ===\n");

    // ── 1. ErrorCode enum ──

    println!("1. ErrorCode variants (8 common + #[non_exhaustive]):");
    let codes = [
        ErrorCode::Success,
        ErrorCode::BadRequest,
        ErrorCode::Unauthorized,
        ErrorCode::Forbidden,
        ErrorCode::NotFound,
        ErrorCode::Conflict,
        ErrorCode::ValidationError,
        ErrorCode::InternalError,
    ];
    for code in codes {
        println!("   {:?} = {} ({})", code, code.as_i32(), code.as_str());
    }

    // ── 2. ErrorCode::from_i32() / as_i32() ──

    println!("\n2. Integer <-> ErrorCode conversion:");
    println!("   from_i32(404) = {:?}", ErrorCode::from_i32(404));
    println!("   from_i32(999) = {:?} (unknown code)", ErrorCode::from_i32(999));
    println!("   NotFound.as_i32() = {}", ErrorCode::NotFound.as_i32());

    // ── 3. is_success() / is_error() ──

    println!("\n3. ApiResult query methods:");

    let ok: ApiResult<User> = ApiResult::value(User { id: 1, name: "Alice".into() });
    let fail: ApiResult<User> = ApiResult::fail("Not found").with_code(404);

    println!("   success response: is_success={}, is_error={}", ok.is_success(), ok.is_error());
    println!("   error response:   is_success={}, is_error={}", fail.is_success(), fail.is_error());

    // ── 4. error_code() — extract ErrorCode from error responses ──

    println!("\n4. error_code() query:");
    println!("   success response error_code() = {:?}", ok.error_code());
    println!("   error response error_code()   = {:?}", fail.error_code());

    // ── 5. Client-side deserialization ──
    //
    // A real client would receive JSON from an API endpoint,
    // deserialize it, and then use query methods to branch.

    println!("\n5. Client-side deserialization pattern:");

    let json = r#"{"success":true,"data":{"id":1,"name":"Alice"}}"#;
    let parsed: ApiResult<User> = serde_json::from_str(json).unwrap();

    if parsed.is_success() {
        // Safe to access data
        if let Some(data) = &parsed.data {
            println!("   Got user: id={}, name={}", data.as_single().map(|u| u.id).unwrap_or(0), data.as_single().map(|u| u.name.as_str()).unwrap_or(""));
        }
    }

    // Deserialize an error response
    let error_json = r#"{"success":false,"message":"Validation failed","code":422,"errors":[{"field":"email","message":"invalid format"}]}"#;
    let error_resp: ApiResult<User> = serde_json::from_str(error_json).unwrap();

    if error_resp.is_error() {
        let code = error_resp.error_code();
        println!("   Error: {} (code={:?})", error_resp.message.as_deref().unwrap_or(""), code);
        if let Some(errors) = &error_resp.errors {
            for fe in errors {
                println!("     field '{}': {}", fe.field, fe.message);
            }
        }
    }

    // ── 6. with_code() maps to ErrorCode -> HTTP status ──

    println!("\n6. with_code() for different error types:");
    let examples: Vec<(&str, i32)> = vec![
        ("Bad Request", 400),
        ("Unauthorized", 401),
        ("Forbidden", 403),
        ("Not Found", 404),
        ("Conflict", 409),
        ("Validation Failed", 422),
        ("Internal Error", 500),
    ];

    for (msg, code) in examples {
        let resp: ApiResult<User> = ApiResult::fail(msg).with_code(code);
        println!("   code={} -> error_code()={:?}", code, resp.error_code());
    }

    println!("\n=== Demo complete ===");
}
