use clap::{Parser, Subcommand};
use std::env;
use std::process;

mod task;
mod hash;
mod file;
mod commands;

#[derive(Parser)]
#[command(name = "citrine", version, about = "Minimalist plaintext todo CLI")]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Initialize citrine in current directory
    Init,
    /// Add a new task
    Add {
        /// Task description
        description: String,
        /// Add to .citrine.local instead
        #[arg(long)]
        local: bool,
    },
    /// List tasks
    List {
        /// Filter by status: todo, progress, blocked, done
        #[arg(long)]
        status: Option<String>,
        /// Show only local tasks
        #[arg(long)]
        local: bool,
    },
    /// Set task status
    Set {
        /// Task hash (full or partial)
        hash: String,
        /// New status: todo, progress, blocked, done
        status: String,
    },
    /// Mark task as done
    Done {
        /// Task hash (full or partial)
        hash: String,
    },
    /// Remove a task
    Rm {
        /// Task hash (full or partial)
        hash: String,
    },
}

fn main() {
    let cli = Cli::parse();
    let dir = env::current_dir().unwrap_or_else(|e| {
        eprintln!("Error: {}", e);
        process::exit(1);
    });

    let result = match cli.command {
        Commands::Init => commands::init::run(&dir),
        Commands::Add { description, local } => commands::add::run(&dir, &description, local),
        Commands::List { status, local } => commands::list::run(&dir, status.as_deref(), local),
        Commands::Set { hash, status } => commands::set::run(&dir, &hash, &status),
        Commands::Done { hash } => commands::set::run(&dir, &hash, "done"),
        Commands::Rm { hash } => commands::rm::run(&dir, &hash),
    };

    if let Err(e) = result {
        let msg = e.to_string();
        eprintln!("Error: {}", msg);
        if msg.contains("Not initialized") {
            process::exit(3);
        } else if msg.contains("Invalid status") || msg.contains("Ambiguous hash") {
            process::exit(2);
        } else {
            process::exit(1);
        }
    }
}
