use chrono::Datelike;
use common_contracts::dtos::{CompanyProfileDto, TimeSeriesFinancialDto};
use common_contracts::messages::{CompanyProfilePersistedEvent, FetchCompanyDataCommand, FinancialsPersistedEvent};
use crate::error::Result;
use crate::persistence::PersistenceClient;
use crate::state::AppState;
use tracing::info;

pub async fn handle_fetch_command(
    state: AppState,
    command: FetchCompanyDataCommand,
    publisher: async_nats::Client,
) -> Result<()> {
    let task_id = command.request_id;
    state.tasks.insert(task_id, common_contracts::observability::TaskProgress {
        request_id: task_id,
        task_name: format!("yfinance:{}", command.symbol),
        status: "FetchingData".to_string(),
        progress_percent: 10,
        details: "Fetching data from YFinance".to_string(),
        started_at: chrono::Utc::now(),
    });

    // Fetch
    let (profile, financials): (CompanyProfileDto, Vec<TimeSeriesFinancialDto>) =
        state.yfinance_provider.fetch_all_data(&command.symbol).await?;

    // Persist
    {
        if let Some(mut task) = state.tasks.get_mut(&task_id) {
            task.status = "PersistingData".to_string();
            task.progress_percent = 60;
            task.details = "Persisting data".to_string();
        }
    }
    let client = PersistenceClient::new(state.config.data_persistence_service_url.clone());
    client.upsert_company_profile(profile).await?;
    let years: std::collections::BTreeSet<u16> = financials.iter().map(|f| f.period_date.year() as u16).collect();
    client.batch_insert_financials(financials).await?;

    // Publish events
    let profile_event = CompanyProfilePersistedEvent {
        request_id: task_id,
        symbol: command.symbol.clone(),
    };
    publisher
        .publish(
            "events.data.company_profile_persisted".to_string(),
            serde_json::to_vec(&profile_event).unwrap().into(),
        )
        .await?;

    let financials_event = FinancialsPersistedEvent {
        request_id: task_id,
        symbol: command.symbol.clone(),
        years_updated: years.into_iter().collect(),
    };
    publisher
        .publish(
            "events.data.financials_persisted".to_string(),
            serde_json::to_vec(&financials_event).unwrap().into(),
        )
        .await?;

    if let Some(mut task) = state.tasks.get_mut(&task_id) {
        task.status = "Completed".to_string();
        task.progress_percent = 100;
        task.details = "Workflow finished successfully".to_string();
    }
    info!("Task {} completed successfully.", task_id);
    Ok(())
}
