use std::fs;
use std::path::Path;

use crate::metadata::EffectMetadata;
use crate::pipl::derive_flags;

pub fn write_effect_meta(out_dir: &Path, m: &EffectMetadata) {
	let (out_flags, out_flags_2) = derive_flags(m);
	let support_url = match m.support_url.as_deref() {
		Some(url) => format!("Some(\"{url}\")"),
		None => "None".into(),
	};

	let version = parse_version();

	let contents = format!(
		"// Generated by prgpu-build — single source of truth shared with the PiPL\n\
		 pub const PRGPU_EFFECT_META: ::prgpu::effect::EffectMeta = ::prgpu::effect::EffectMeta {{\n\
		     match_name: \"{}\",\n\
		     display_name: \"{}\",\n\
		     category: \"{}\",\n\
		     version: ({}, {}, {}),\n\
		     support_url: {},\n\
		     out_flags: 0x{:016x},\n\
		     out_flags_2: 0x{:016x},\n\
		     expansion: {},\n\
		     gpu: {},\n\
		 }};\n",
		escape(m.match_name),
		escape(m.display_name),
		escape(m.category),
		version.0,
		version.1,
		version.2,
		support_url,
		out_flags.bits() as u64,
		out_flags_2.bits() as u64,
		m.expansion,
		m.gpu,
	);

	let path = out_dir.join("prgpu_effect_meta.rs");
	fs::write(&path, contents).unwrap_or_else(|e| panic!("failed to write {}: {e}", path.display()));
}

fn escape(s: &str) -> String {
	s.replace('\\', "\\\\").replace('"', "\\\"")
}

fn parse_version() -> (u32, u32, u32) {
	let vers = std::env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "0.0.0".into());
	let mut parts = vers.split('.');
	let major = parts.next().and_then(|s| s.parse().ok()).unwrap_or(0);
	let minor = parts.next().and_then(|s| s.parse().ok()).unwrap_or(0);
	let patch = parts
		.next()
		.unwrap_or("0")
		.split('-')
		.next()
		.and_then(|s| s.parse().ok())
		.unwrap_or(0);
	(major, minor, patch)
}
