use std::sync::Arc;

use alloy::{json_abi::Event, rpc::types::Filter};
use anyhow::Result;
use clap::Parser;
use ethl::{
    archive::extract::EventExtractor, rpc::config::ProviderSettings,
    storage::store::parse_store_uri,
};
use tracing::debug;

use crate::commands::FilterArgs;

#[derive(Parser, Debug)]
pub struct ExtractArgs {
    /// Filter arguments for scoping log queries
    #[command(flatten)]
    filter_args: FilterArgs,

    /// The output directory for the archived logs (eg: file:///tmp/events or s3://my-bucket/events)
    #[arg(long, required = true)]
    output: String,

    /// The target number of events per parquet file (default: 200,000)
    #[arg(long, default_value_t = 200_000)]
    target_events_per_file: usize,
}

pub async fn extract_events(providers: &ProviderSettings, args: ExtractArgs) -> Result<()> {
    debug!("Extracting events: {:?} - {:?}", args, providers);

    let events: Option<Vec<Event>> = (&args.filter_args).try_into()?;
    let filter: Option<Filter> = (&args.filter_args).try_into()?;
    let (store, path) = parse_store_uri(&args.output)?;
    if events.is_none() {
        return Err(anyhow::anyhow!(
            "At least one valid --event must be specified for the extract command"
        ));
    }

    let mut indexer = EventExtractor::new(
        Arc::new(store),
        path,
        args.target_events_per_file,
        providers.clone(),
        events.unwrap(),
        filter.unwrap(),
    )?;

    indexer.extract().await?;

    Ok(())
}
