use crate::{
    db,
    dtos::{CompanyProfileDto, ProviderStatusDto},
    AppState, ServerError,
};
use axum::{
    extract::{Path, State},
    Json,
};
use service_kit::api;
use tracing::info;
use anyhow::Error as AnyhowError;

#[api(PUT, "/api/v1/companies")]
pub async fn upsert_company(
    State(state): State<AppState>,
    Json(payload): Json<CompanyProfileDto>,
) -> Result<(), ServerError> {
    info!(target: "api", symbol = %payload.symbol, "PUT /companies → upsert_company called");
    db::companies::upsert_company(&state.pool, &payload).await.map_err(AnyhowError::from)?;
    info!(target: "api", symbol = %payload.symbol, "upsert_company completed");
    Ok(())
}

#[api(GET, "/api/v1/companies/{symbol}")]
pub async fn get_company_by_symbol(
    State(state): State<AppState>,
    Path(symbol): Path<String>,
) -> Result<Json<CompanyProfileDto>, ServerError> {
    info!(target: "api", symbol = %symbol, "GET /companies/{{symbol}} → get_company_by_symbol called");
    let company = db::companies::get_company_by_symbol(&state.pool, &symbol)
        .await
        .map_err(AnyhowError::from)?
        .ok_or_else(|| ServerError::NotFound(format!("Company with symbol '{}' not found", symbol)))?;

    // Convert from model to DTO
    let dto = CompanyProfileDto {
        symbol: company.symbol,
        name: company.name,
        industry: company.industry,
        list_date: company.list_date,
        additional_info: company.additional_info,
        updated_at: Some(company.updated_at),
    };

    info!(target: "api", symbol = %dto.symbol, "get_company_by_symbol completed");
    Ok(Json(dto))
}


#[api(
    PUT,
    "/api/v1/companies/{symbol}/providers/{provider_id}/status"
)]
pub async fn update_provider_status(
    State(state): State<AppState>,
    Path((symbol, provider_id)): Path<(String, String)>,
    Json(payload): Json<ProviderStatusDto>,
) -> Result<(), ServerError> {
    info!(target: "api", symbol = %symbol, provider = %provider_id, "PUT provider status");
    db::companies::update_provider_status(&state.pool, &symbol, &provider_id, &payload)
        .await
        .map_err(AnyhowError::from)?;
    Ok(())
}

#[api(
    GET,
    "/api/v1/companies/{symbol}/providers/{provider_id}/status"
)]
pub async fn get_provider_status(
    State(state): State<AppState>,
    Path((symbol, provider_id)): Path<(String, String)>,
) -> Result<Json<Option<ProviderStatusDto>>, ServerError> {
    info!(target: "api", symbol = %symbol, provider = %provider_id, "GET provider status");
    let status = db::companies::get_provider_status(&state.pool, &symbol, &provider_id)
        .await
        .map_err(AnyhowError::from)?;
    Ok(Json(status))
}

