use crate::{AppState, ServerError};
use axum::{
    extract::{Path, Query, State},
    http::StatusCode,
    response::IntoResponse,
    Json,
};
use common_contracts::dtos::{NewWorkflowHistory, WorkflowHistoryDto, WorkflowHistorySummaryDto};
// use serde::Deserialize;
use service_kit::{api, api_dto};
use tracing::{error, instrument};
use anyhow::Error as AnyhowError;
use uuid::Uuid;

#[api_dto]
#[derive(utoipa::IntoParams)]
pub struct HistoryQuery {
    pub symbol: Option<String>,
    pub limit: Option<i64>,
}

#[instrument(skip(state, payload))]
#[api(POST, "/api/v1/history")]
pub async fn create_workflow_history(
    State(state): State<AppState>,
    Json(payload): Json<NewWorkflowHistory>,
) -> Result<impl IntoResponse, ServerError> {
    let result = crate::db::history::create_workflow_history(state.pool(), &payload)
        .await
        .map_err(|e| {
            error!("Database error inserting workflow history: {}", e);
            AnyhowError::from(e)
        })?;

    let dto = WorkflowHistoryDto {
        request_id: result.request_id,
        symbol: result.symbol,
        market: result.market,
        template_id: result.template_id,
        status: result.status,
        start_time: result.start_time,
        end_time: result.end_time,
        snapshot_data: result.snapshot_data,
        created_at: result.created_at,
    };

    Ok((StatusCode::CREATED, Json(dto)))
}

#[instrument(skip(state))]
#[api(GET, "/api/v1/history")]
pub async fn get_workflow_histories(
    State(state): State<AppState>,
    Query(query): Query<HistoryQuery>,
) -> Result<Json<Vec<WorkflowHistorySummaryDto>>, ServerError> {
    let limit = query.limit.unwrap_or(20).min(100);
    let results = crate::db::history::get_workflow_histories(state.pool(), query.symbol.as_deref(), limit)
        .await
        .map_err(|e| {
            error!("Database error fetching workflow histories: {}", e);
            AnyhowError::from(e)
        })?;

    let dtos = results
        .into_iter()
        .map(|r| WorkflowHistorySummaryDto {
            request_id: r.request_id,
            symbol: r.symbol,
            market: r.market,
            template_id: r.template_id,
            status: r.status,
            start_time: r.start_time,
            end_time: r.end_time,
        })
        .collect();

    Ok(Json(dtos))
}

#[instrument(skip(state))]
#[api(GET, "/api/v1/history/{request_id}")]
pub async fn get_workflow_history_by_id(
    State(state): State<AppState>,
    Path(request_id_str): Path<String>,
) -> Result<Json<WorkflowHistoryDto>, ServerError> {
    let request_id = Uuid::parse_str(&request_id_str).map_err(|_| ServerError::NotFound(format!("Invalid UUID: {}", request_id_str)))?;

    let result = crate::db::history::get_workflow_history_by_id(state.pool(), request_id)
        .await
        .map_err(|e| {
            error!("Database error fetching workflow history by id: {}", e);
            AnyhowError::from(e)
        })?
        .ok_or_else(|| ServerError::NotFound(format!("History not found: {}", request_id)))?;

    let dto = WorkflowHistoryDto {
        request_id: result.request_id,
        symbol: result.symbol,
        market: result.market,
        template_id: result.template_id,
        status: result.status,
        start_time: result.start_time,
        end_time: result.end_time,
        snapshot_data: result.snapshot_data,
        created_at: result.created_at,
    };

    Ok(Json(dto))
}

