use std::{
    io::{BufReader, Read, Write},
    path::PathBuf,
    process::Command,
};

use clap::{Parser, Subcommand};

use icu_locid::{langid, LanguageIdentifier};
use l10n_db::{self, js, read_file, xliff, Bundle, Editor, ReadError};
use serde::Deserialize;

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Option<Commands>,
}

#[derive(Subcommand)]
enum Commands {
    /// Edit, potentially creating, a key
    EditKey {
        #[arg(short, long)]
        name: String,
        #[arg(short, long)]
        locale: String,
    },
    /// List al keys in the database
    ListKeys,
    // Search the database
    // Search { },
    /// Export the database
    Export {
        #[arg(short, long)]
        format: String,
        #[arg(short, long)]
        locale: Option<String>,
    },
}

#[derive(Debug, Deserialize)]
struct Config {
    db_path: PathBuf,
    base_locale: LanguageIdentifier,
    locales: Vec<LanguageIdentifier>,
}

fn edit_key(bundle: &mut Bundle, key: String, locale: LanguageIdentifier, editor: &str) {
    let message = bundle.message(key);
    Editor::edit(message, locale, editor);
    bundle.save();
}

fn main() {
    let editor = std::env::var("EDITOR").expect("Set EDITOR to the path to your favorite editor");

    let config: Config = read_file(&PathBuf::from("./config.toml"))
        .and_then(|bytes| String::from_utf8(bytes).map_err(|_| ReadError::InvalidFormat))
        .and_then(|content| toml::from_str(&content).map_err(|_| ReadError::InvalidFormat))
        .unwrap();

    let cli = Cli::parse();

    let mut bundle = Bundle::load_from_disk(PathBuf::from(&config.db_path));

    match &cli.command {
        Some(Commands::EditKey { name, locale }) => {
            let identifier = locale.parse::<LanguageIdentifier>().unwrap();
            edit_key(&mut bundle, name.to_owned(), identifier, &editor)
        }
        Some(Commands::ListKeys) => {
            for (key, _) in bundle.message_iter() {
                println!("{}", key);
            }
        }
        Some(Commands::Export { format, locale }) => {
            let locale = locale.as_ref().map(|l| l.clone().parse::<LanguageIdentifier>().unwrap()).unwrap_or(langid!("en"));

            match format.as_ref() {
                "js" => js::export_file(&bundle, locale, &PathBuf::from("output.json")).unwrap(),
                "xliff" => xliff::export_file(&bundle, locale, &PathBuf::from("output.xliff")).unwrap(),
                _ => todo!(),
            }
        },
        None => {}
    }
}