//! {{TOOL_NAME}} REST API
//!
//! HTTP API server for {{TOOL_NAME}}.

use axum::{
    extract::{Path, State},
    http::StatusCode,
    routing::{get, post, put, delete},
    Json, Router,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use {{TOOL_NAME}}_core::*;

#[derive(Clone)]
struct AppState {
    service: {{MainType}}Service,
}

#[derive(Serialize, Deserialize)]
struct CreateRequest {
    name: String,
    description: String,
}

#[tokio::main]
async fn main() -> Result<()> {
    // Initialize logging
    tracing_subscriber::fmt()
        .with_env_filter("info")
        .init();

    let state = AppState {
        service: {{MainType}}Service::new(),
    };

    let app = Router::new()
        .route("/health", get(health_check))
        .route("/{{main_type_plural}}", get(list_items).post(create_item))
        .route("/{{main_type_plural}}/:id", get(get_item).put(update_item).delete(delete_item))
        .with_state(Arc::new(state));

    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
        .await
        .expect("Failed to bind port 3000");

    tracing::info!("Server listening on http://127.0.0.1:3000");

    axum::serve(listener, app)
        .await
        .expect("Server error");

    Ok(())
}

async fn health_check() -> StatusCode {
    StatusCode::OK
}

async fn list_items(State(state): State<Arc<AppState>>) -> Json<Vec<{{MainType}}>> {
    match state.service.list().await {
        Ok(items) => Json(items),
        Err(_) => Json(vec![]),
    }
}

async fn get_item(
    State(state): State<Arc<AppState>>,
    Path(id): Path<String>,
) -> Result<Json<{{MainType}}>, StatusCode> {
    state.service.get(&id).await
        .map(Json)
        .map_err(|_| StatusCode::NOT_FOUND)
}

async fn create_item(
    State(state): State<Arc<AppState>>,
    Json(req): Json<CreateRequest>,
) -> Result<Json<{{MainType}}>, StatusCode> {
    state.service.create(req.name, req.description).await
        .map(Json)
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}

async fn update_item(
    State(state): State<Arc<AppState>>,
    Path(id): Path<String>,
    Json(req): Json<CreateRequest>,
) -> Result<Json<{{MainType}}>, StatusCode> {
    state.service.update(&id, req.name, req.description).await
        .map(Json)
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}

async fn delete_item(
    State(state): State<Arc<AppState>>,
    Path(id): Path<String>,
) -> StatusCode {
    match state.service.delete(&id).await {
        Ok(_) => StatusCode::NO_CONTENT,
        Err(_) => StatusCode::NOT_FOUND,
    }
}
