use crate::error::Result;
use crate::state::AppState;
use common_contracts::messages::FetchCompanyDataCommand;
use common_contracts::subjects::NatsSubject;
use futures_util::StreamExt;
use tracing::{error, info};

pub async fn run(state: AppState) -> Result<()> {
    info!("Starting NATS message consumer...");

    let client = async_nats::connect(&state.config.nats_addr).await?;
    info!("Connected to NATS.");

    // This is a simple subscriber. For production, consider JetStream for durability.
    let subject = NatsSubject::DataFetchCommands.to_string();
    let mut subscriber = client.subscribe(subject.clone()).await?;

    info!(
        "Consumer started, waiting for messages on subject '{}'",
        subject
    );

    while let Some(message) = subscriber.next().await {
        info!("Received NATS message.");
        let state_clone = state.clone();
        let publisher_clone = client.clone();

        tokio::spawn(async move {
            match serde_json::from_slice::<FetchCompanyDataCommand>(&message.payload) {
                Ok(command) => {
                    let request_id = command.request_id;
                    info!("Deserialized command for symbol: {}", command.symbol);
                    if let Err(e) =
                        crate::worker::handle_fetch_command(state_clone.clone(), command, publisher_clone)
                            .await
                    {
                        error!("Error handling fetch command: {:?}", e);
                        if let Some(mut task) = state_clone.tasks.get_mut(&request_id) {
                            task.status = common_contracts::observability::ObservabilityTaskStatus::Failed;
                            task.details = format!("Worker failed: {}", e);
                        }
                    }
                }
                Err(e) => {
                    error!("Failed to deserialize message: {}", e);
                }
            }
        });
    }

    Ok(())
}
