use std::io::stdin;

use anyhow::anyhow;
use clap::{Parser, Subcommand};
use rocket::{Orbit, Rocket};
use rocket_db_pools::Database;

use crate::db::{reseed::reseed_db, schema::DollTags};

#[derive(Parser, Debug)]
#[command(about = "dolltags.pet admin and management CLI", long_about = None)]
pub struct AdminCli {
	#[command(subcommand)]
	command: Option<Commands>,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
	/// [DESTRUCTIVE] Re-seeds the dolltags database after deleting all its content
	ReseedDb {},
}

pub async fn handle_cli<'a>(
	command: Commands,
	rocket: &'a Rocket<Orbit>,
) -> Result<(), anyhow::Error> {
	match command {
		Commands::ReseedDb {} => {
			println!("Reseeding the DB means deleting everything currently in it then applying the test seed data,");
			println!("are you aware of the risks and connected to the right database? (write Y or YES in caps to confirm, anything else to cancel)");

			let mut input = String::new();
			stdin().read_line(&mut input).expect("unable to read stdin");
			input = String::from(input.trim());

			if input == "Y" || input == "YES" {
				println!("Resetting/Reseeding the DB");
				let db = match DollTags::fetch(&rocket) {
					Some(v) => v,
					None => return Err(anyhow!("couldn't get a db hook")),
				};
				let mut trx = db.begin().await?;
				reseed_db(&mut trx).await?;
				trx.commit().await?;

				println!("Reset and reseeded the DB");
			} else {
				println!("Cancelled the reset/reseed");
			}
		}
	}

	Ok(())
}

pub async fn check_cli_invocation<'a>(rocket: &'a Rocket<Orbit>) -> () {
	let cli = AdminCli::parse();
	let shutdown = rocket.shutdown();

	match cli.command {
		None => (),
		Some(cmd) => {
			if let Err(e) = handle_cli(cmd, rocket).await {
				error!("failed to handle command: {:?}", e);
			}

			shutdown.notify();
		}
	}

	()
}
