use serde::Serialize;
use std::fs;
use std::path::{Path, PathBuf};

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InjectedRule {
    /// 规则文件名（不含 .md），由规则名 slug 化而来
    pub slug: String,
    /// CLAUDE.md 中是否存在对应的 @ 引用行（即是否启用）
    pub enabled: bool,
}

/// 规则名 -> 文件名 slug：保留中英文与数字，其余替换为 '-'
pub fn slugify(name: &str) -> String {
    let mut out = String::new();
    for c in name.chars() {
        if c.is_alphanumeric() {
            out.push(c);
        } else {
            out.push('-');
        }
    }
    let collapsed = out
        .split('-')
        .filter(|s| !s.is_empty())
        .collect::<Vec<_>>()
        .join("-");
    if collapsed.is_empty() {
        "rule".into()
    } else {
        collapsed
    }
}

fn rules_dir(project: &str) -> PathBuf {
    Path::new(project).join(".claude").join("rules")
}

fn claudemd_path(project: &str) -> PathBuf {
    Path::new(project).join("CLAUDE.md")
}

fn import_line(slug: &str) -> String {
    format!("@.claude/rules/{slug}.md")
}

pub fn read_claudemd(project: &str) -> String {
    fs::read_to_string(claudemd_path(project)).unwrap_or_default()
}

pub fn write_claudemd(project: &str, content: &str) -> Result<(), String> {
    fs::write(claudemd_path(project), content).map_err(|e| e.to_string())
}

/// 列出项目中已注入的规则：以 .claude/rules/ 目录下的文件为准，
/// 同时检查 CLAUDE.md 中引用行是否存在（决定启用状态）
pub fn list_injected(project: &str) -> Vec<InjectedRule> {
    let dir = rules_dir(project);
    let claudemd = read_claudemd(project);
    let mut out = Vec::new();
    let Ok(entries) = fs::read_dir(&dir) else {
        return out;
    };
    for entry in entries.flatten() {
        let path = entry.path();
        if path.extension().and_then(|e| e.to_str()) != Some("md") {
            continue;
        }
        let Some(slug) = path.file_stem().map(|s| s.to_string_lossy().into_owned()) else {
            continue;
        };
        let enabled = claudemd
            .lines()
            .any(|l| l.trim() == import_line(&slug));
        out.push(InjectedRule { slug, enabled });
    }
    out.sort_by(|a, b| a.slug.cmp(&b.slug));
    out
}

/// 注入规则：写规则文件 + 在 CLAUDE.md 末尾追加 @ 引用行（幂等）
pub fn inject(project: &str, rule_name: &str, content: &str) -> Result<String, String> {
    let slug = slugify(rule_name);
    let dir = rules_dir(project);
    fs::create_dir_all(&dir).map_err(|e| e.to_string())?;
    fs::write(dir.join(format!("{slug}.md")), content).map_err(|e| e.to_string())?;
    set_enabled(project, &slug, true)?;
    Ok(slug)
}

/// 启用/停用：增删 CLAUDE.md 中的引用行，规则文件保留
pub fn set_enabled(project: &str, slug: &str, enabled: bool) -> Result<(), String> {
    let line = import_line(slug);
    let current = read_claudemd(project);
    let has = current.lines().any(|l| l.trim() == line);
    if enabled && !has {
        let mut next = current;
        if !next.is_empty() && !next.ends_with('\n') {
            next.push('\n');
        }
        next.push_str(&line);
        next.push('\n');
        write_claudemd(project, &next)
    } else if !enabled && has {
        let next: String = current
            .lines()
            .filter(|l| l.trim() != line)
            .collect::<Vec<_>>()
            .join("\n");
        // 保持文件末尾换行的习惯
        let next = if next.is_empty() { next } else { next + "\n" };
        write_claudemd(project, &next)
    } else {
        Ok(())
    }
}

/// 彻底移除：删除引用行 + 删除规则文件
pub fn remove(project: &str, slug: &str) -> Result<(), String> {
    set_enabled(project, slug, false)?;
    let file = rules_dir(project).join(format!("{slug}.md"));
    if file.exists() {
        fs::remove_file(&file).map_err(|e| e.to_string())?;
    }
    Ok(())
}

/// 读取某条已注入规则的当前内容（用于和规则库内容比对/重新注入）
pub fn read_injected(project: &str, slug: &str) -> String {
    fs::read_to_string(rules_dir(project).join(format!("{slug}.md"))).unwrap_or_default()
}
