mod config;
mod docker_config;
mod fetcher;

use std::io::Write;

use clap::{arg, Parser, Subcommand};

use crate::{
    config::{read_registry_config, write_registry_config},
    fetcher::{Fetcher, FetcherType},
};
use fetcher::QueryArgs;

#[derive(Parser)]
#[command(
    name = "dockertags",
    author,
    version,
    about = "List all tags for a Docker image on a remote docker_registry",
    long_about = "List all tags for a Docker image on a remote docker_registry"
)]
struct Args {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// List all tags for a Docker image
    List {
        /// docker image name
        #[arg(value_name = "REPOSITORY")]
        repository: String,
        /// docker image architecture
        #[arg(short, long, value_name = "ARCHITECTURE")]
        arch: Option<String>,
        /// image tags name to filter
        #[arg(short, long, value_name = "TAG")]
        filter: Option<String>,
    },
    /// Manage registry configuration
    Registry {
        /// Set the registry URL
        #[arg(long, value_name = "URL")]
        set_url: Option<String>,
    },
}

#[tokio::main]
async fn main() {
    let args = Args::parse();

    match args.command {
        Commands::List {
            repository,
            arch,
            filter,
        } => {
            let query_args = QueryArgs::new(&repository, filter, arch);

            // read config
            let registry_config = read_registry_config();
            let docker_auth_config = docker_config::read_config();

            let fetcher = match (registry_config, docker_auth_config) {
                (Some(_), Some(auth)) => Fetcher::create_fetcher(FetcherType::Registry(auth)),
                _ => Fetcher::create_fetcher(FetcherType::DockerHub),
            };

            let mut tags = fetcher.fetch(&query_args).await.unwrap();

            tags.sort();
            for tag in tags {
                let _ = writeln!(std::io::stdout(), "{}", &tag);
            }
        }
        Commands::Registry { set_url } => {
            if let Some(url) = set_url {
                if let Err(e) = write_registry_config(&url, "v2") {
                    eprintln!("Failed to write registry config: {e}");
                } else {
                    println!("Registry URL set to: {url}");
                }
            } else {
                eprintln!("No URL provided. Use --set-url to specify the registry URL.");
            }
        }
    };
}
