// SPDX-License-Identifier: GPL-3.0-or-later

use clap::{Parser, Subcommand, ValueEnum};
use std::io::Write;

use crate::i18n::tr;

#[derive(Parser)]
#[command(name = "temperlux", version, about = tr("cli.about"))]
pub enum Cli {
    #[command(about = tr("cli.list.about"))]
    List {
        #[arg(long, help = tr("cli.list.json_help"))]
        json: bool,
    },

    #[command(about = tr("cli.get.about"))]
    Get {
        #[arg(help = tr("cli.get.display_help"))]
        display: usize,
    },

    #[command(about = tr("cli.set.about"))]
    Set {
        #[arg(help = tr("cli.set.display_help"))]
        display: Option<usize>,
        #[arg(long, help = tr("cli.set.percent_help"))]
        percent: f64,
    },

    #[command(about = tr("cli.increase.about"))]
    Increase {
        #[arg(help = tr("cli.increase.display_help"))]
        display: Option<usize>,
        #[arg(long, help = tr("cli.increase.percent_help"))]
        percent: f64,
    },

    #[command(about = tr("cli.decrease.about"))]
    Decrease {
        #[arg(help = tr("cli.decrease.display_help"))]
        display: Option<usize>,
        #[arg(long, help = tr("cli.decrease.percent_help"))]
        percent: f64,
    },

    #[command(about = tr("cli.rename.about"))]
    Rename {
        #[arg(help = tr("cli.rename.display_help"))]
        display: usize,
        #[arg(help = tr("cli.rename.name_help"))]
        name: String,
    },

    #[command(about = tr("cli.caps.about"))]
    Caps {
        #[arg(help = tr("cli.caps.display_help"))]
        display: usize,
        #[arg(long, help = tr("cli.caps.min_help"))]
        min: Option<f64>,
        #[arg(long, help = tr("cli.caps.max_help"))]
        max: Option<f64>,
    },

    #[command(about = tr("cli.sync.about"))]
    Sync {
        #[arg(help = tr("cli.sync.mode_help"))]
        mode: SyncModeArg,
    },

    #[command(about = tr("cli.order.about"))]
    Order {
        #[arg(help = tr("cli.order.display_help"))]
        display: usize,
        #[arg(long, help = tr("cli.order.up_help"))]
        up: bool,
        #[arg(long, help = tr("cli.order.down_help"))]
        down: bool,
    },

    #[command(about = tr("cli.autostart.about"))]
    Autostart {
        #[arg(help = tr("cli.autostart.enabled_help"))]
        enabled: bool,
    },

    #[command(about = tr("cli.config.about"))]
    Config {
        #[arg(long, help = tr("cli.config.show_numbers_help"))]
        show_numbers: Option<bool>,

        #[arg(long, help = tr("cli.config.use_24h_help"))]
        use_24h: Option<bool>,

        #[arg(long, help = tr("cli.config.show_range_help"))]
        show_range_labels: Option<bool>,
    },

    #[command(about = tr("cli.schedule.about"))]
    Schedule {
        #[command(subcommand)]
        command: ScheduleCommand,
    },

    #[command(about = tr("cli.completions.about"))]
    Completions {
        #[arg(help = tr("cli.completions.shell_help"))]
        shell: Shell,
    },
}

#[derive(Subcommand)]
pub enum ScheduleCommand {
    #[command(about = tr("cli.schedule.list.about"))]
    List {
        #[arg(long, help = tr("cli.schedule.list.json_help"))]
        json: bool,
    },

    #[command(about = tr("cli.schedule.add.about"))]
    Add {
        #[arg(long, help = tr("cli.schedule.add.name_help"))]
        name: String,

        #[arg(long, value_delimiter = ',', help = tr("cli.schedule.add.monitors_help"))]
        monitors: Vec<String>,

        #[arg(long, help = tr("cli.schedule.add.time_help"))]
        time: Option<String>,

        #[arg(long, allow_negative_numbers = true, help = tr("cli.schedule.add.after_sunrise_help"))]
        after_sunrise: Option<i32>,

        #[arg(long, allow_negative_numbers = true, help = tr("cli.schedule.add.after_sunset_help"))]
        after_sunset: Option<i32>,
    },

    #[command(about = tr("cli.schedule.edit.about"))]
    Edit {
        #[arg(help = tr("cli.schedule.edit.id_help"))]
        id: String,

        #[arg(long, help = tr("cli.schedule.edit.name_help"))]
        name: Option<String>,

        #[arg(long, value_delimiter = ',', help = tr("cli.schedule.edit.monitors_help"))]
        monitors: Option<Vec<String>>,

        #[arg(long, help = tr("cli.schedule.edit.time_help"))]
        time: Option<String>,

        #[arg(long, allow_negative_numbers = true, help = tr("cli.schedule.edit.after_sunrise_help"))]
        after_sunrise: Option<i32>,

        #[arg(long, allow_negative_numbers = true, help = tr("cli.schedule.edit.after_sunset_help"))]
        after_sunset: Option<i32>,

        #[arg(long, help = tr("cli.schedule.edit.remove_trigger_help"))]
        remove_trigger: Option<usize>,

        #[arg(long, help = tr("cli.schedule.edit.enabled_help"))]
        enabled: Option<bool>,
    },

    #[command(about = tr("cli.schedule.delete.about"))]
    Delete {
        #[arg(help = tr("cli.schedule.delete.id_help"))]
        id: String,
    },

    #[command(about = tr("cli.schedule.apply.about"))]
    Apply {
        #[arg(long, help = tr("cli.schedule.apply.profile_help"))]
        profile: Option<String>,
    },

    #[command(about = tr("cli.schedule.show_times.about"))]
    ShowTimes,

    #[command(about = tr("cli.schedule.generate_timers.about"))]
    GenerateTimers,

    #[command(about = tr("cli.schedule.location.about"))]
    Location {
        #[arg(long, allow_hyphen_values = true, help = tr("cli.schedule.location.lat_help"))]
        lat: f64,

        #[arg(long, allow_hyphen_values = true, help = tr("cli.schedule.location.lon_help"))]
        lon: f64,
    },

    #[command(about = tr("cli.schedule.detect_location.about"))]
    DetectLocation,
}

#[derive(Clone, ValueEnum)]
pub enum Shell {
    Bash,
    Zsh,
    Fish,
    Elvish,
}

/// Sync mode argument for CLI.
#[derive(Clone, ValueEnum)]
pub enum SyncModeArg {
    Off,
    Same,
    Proportional,
}

pub fn print_completions(shell: Shell) -> anyhow::Result<()> {
    let mut cmd = <Cli as clap::CommandFactory>::command();
    let name = "temperlux".to_string();
    let mut buf = Vec::new();
    match shell {
        Shell::Bash => clap_complete::generate(clap_complete::Shell::Bash, &mut cmd, &name, &mut buf),
        Shell::Zsh => clap_complete::generate(clap_complete::Shell::Zsh, &mut cmd, &name, &mut buf),
        Shell::Fish => clap_complete::generate(clap_complete::Shell::Fish, &mut cmd, &name, &mut buf),
        Shell::Elvish => clap_complete::generate(clap_complete::Shell::Elvish, &mut cmd, &name, &mut buf),
    }
    std::io::stdout().write_all(&buf)?;
    Ok(())
}
