use comfy_table::{presets::UTF8_FULL_CONDENSED, Table, ContentArrangement};
use muzan::DaemonPaths;

use crate::config::{self, Config};
use crate::ipc::{Request, Response};

pub fn init() {
	let path = Config::default_path();
	if path.exists() {
		eprintln!("config already exists: {}", path.display());
		return;
	}
	if let Some(parent) = path.parent() {
		let _ = std::fs::create_dir_all(parent);
	}
	std::fs::write(&path, config::INIT_CONFIG).expect("failed to write config");
	eprintln!("created {}", path.display());
	eprintln!("edit this file, then run `ku daemon start`");
}

pub fn check() {
	let path = Config::default_path();
	if !path.exists() {
		eprintln!("no config found at {}", path.display());
		eprintln!("run `ku init` to create one");
		std::process::exit(1);
	}

	let config = match Config::load(&path) {
		Ok(c) => c,
		Err(e) => {
			eprintln!("error: {}", e);
			std::process::exit(1);
		}
	};

	let errors = config.validate();
	if !errors.is_empty() {
		for e in &errors {
			eprintln!("error: {}", e);
		}
		std::process::exit(1);
	}

	eprintln!("{} job(s) configured\n", config.jobs.len());

	let mut table = Table::new();
	table.load_preset(UTF8_FULL_CONDENSED);
	table.set_content_arrangement(ContentArrangement::Dynamic);
	table.set_header(vec!["NAME", "CRON", "NEXT RUN", "ON_ERROR"]);

	for job in &config.jobs {
		let next = crate::scheduler::next_run_for(&job.cron)
			.map(|dt| dt.format("%Y-%m-%d %H:%M:%S").to_string())
			.unwrap_or_else(|| "—".to_string());

		table.add_row(vec![
			&job.name,
			&job.cron,
			&next,
			&format!("{:?}", job.on_error).to_lowercase(),
		]);
	}

	println!("{table}");
}

pub fn status(json: bool) {
	let paths = DaemonPaths::new("koku");
	let mut client = match muzan::DaemonClient::<Request, Response>::connect(&paths) {
		Ok(c) => c,
		Err(_) => {
			eprintln!("daemon not running — start with `ku daemon start`");
			std::process::exit(1);
		}
	};

	let resp = match client.send(&Request::Status) {
		Ok(r) => r,
		Err(e) => {
			eprintln!("error: {}", e);
			std::process::exit(1);
		}
	};

	match resp {
		Response::Status(statuses) => {
			if json {
				println!("{}", serde_json::to_string_pretty(&statuses).unwrap());
			} else if statuses.is_empty() {
				eprintln!("no jobs configured");
			} else {
				let mut table = Table::new();
				table.load_preset(UTF8_FULL_CONDENSED);
				table.set_content_arrangement(ContentArrangement::Dynamic);
				table.set_header(vec!["NAME", "STATE", "LAST RUN", "EXIT", "NEXT RUN"]);

				for s in &statuses {
					table.add_row(vec![
						&s.name,
						&s.state.to_string(),
						s.last_run.as_deref().unwrap_or("—"),
						&s.last_exit.map(|c| c.to_string()).unwrap_or_else(|| "—".to_string()),
						s.next_run.as_deref().unwrap_or("—"),
					]);
				}

				println!("{table}");
			}
		}
		Response::Error(e) => {
			eprintln!("error: {}", e);
			std::process::exit(1);
		}
		_ => {}
	}
}

pub fn send_command(req: Request) {
	let paths = DaemonPaths::new("koku");
	let mut client = match muzan::DaemonClient::<Request, Response>::connect(&paths) {
		Ok(c) => c,
		Err(_) => {
			eprintln!("daemon not running — start with `ku daemon start`");
			std::process::exit(1);
		}
	};

	match client.send(&req) {
		Ok(Response::Ok(msg)) => eprintln!("{}", msg),
		Ok(Response::Error(msg)) => {
			eprintln!("error: {}", msg);
			std::process::exit(1);
		}
		Ok(Response::Status(_)) => {}
		Err(e) => {
			eprintln!("error: {}", e);
			std::process::exit(1);
		}
	}
}
