use anyhow::Result;
use chrono::{TimeZone, Utc};
use std::path::Path;

use crate::db::Memory;

/// Write memories to IRONMEM.md in the project root.
/// This file is provider-agnostic — readable by any AI coding assistant.
pub fn write_ironmem_file(project_root: &str, memories: &[Memory]) -> Result<()> {
    let path = Path::new(project_root).join("IRONMEM.md");

    if memories.is_empty() {
        // Remove stale file if no memories
        if path.exists() {
            std::fs::remove_file(&path)?;
        }
        return Ok(());
    }

    let mut lines = vec![
        "# IronMem — Session Memory".to_string(),
        format!(
            "> Auto-generated by ironmem. Last updated: {}",
            Utc::now().format("%Y-%m-%d %H:%M UTC")
        ),
        "> Do not edit manually. This file is overwritten each session.".to_string(),
        String::new(),
        "## Recent Session Context".to_string(),
        String::new(),
    ];

    for (i, memory) in memories.iter().enumerate() {
        let date = Utc
            .timestamp_opt(memory.created_at, 0)
            .single()
            .map(|dt| dt.format("%Y-%m-%d").to_string())
            .unwrap_or_else(|| "unknown".to_string());

        lines.push(format!("### Session {} ({})", i + 1, date));
        lines.push(memory.summary.clone());

        if let Some(tags) = &memory.tags {
            if !tags.is_empty() {
                lines.push(format!("**Keywords:** `{}`", tags.replace(' ', "` `")));
            }
        }
        lines.push(String::new());
    }

    std::fs::write(&path, lines.join("\n"))?;
    tracing::info!("Wrote IRONMEM.md to {}", path.display());

    Ok(())
}

/// Ensure CLAUDE.md in the project root has an @IRONMEM.md import.
/// Appends it if missing. Does not duplicate if already present.
pub fn ensure_claude_md_import(project_root: &str) -> Result<()> {
    let claude_md_path = Path::new(project_root).join("CLAUDE.md");
    let import_line = "@IRONMEM.md";

    if claude_md_path.exists() {
        let content = std::fs::read_to_string(&claude_md_path)?;
        if content.contains(import_line) {
            return Ok(()); // Already imported
        }
        // Append the import
        let updated = if content.ends_with('\n') {
            format!("{}\n{}\n", content, import_line)
        } else {
            format!("{}\n\n{}\n", content, import_line)
        };
        std::fs::write(&claude_md_path, updated)?;
        tracing::info!("Added @IRONMEM.md import to CLAUDE.md");
    } else {
        // Create a minimal CLAUDE.md with just the import
        let content = format!("# Project Context\n\n{}\n", import_line);
        std::fs::write(&claude_md_path, content)?;
        tracing::info!("Created CLAUDE.md with @IRONMEM.md import");
    }

    Ok(())
}

/// Remove the @IRONMEM.md import from CLAUDE.md (used on wipe)
pub fn remove_claude_md_import(project_root: &str) -> Result<()> {
    let claude_md_path = Path::new(project_root).join("CLAUDE.md");
    if !claude_md_path.exists() {
        return Ok(());
    }

    let content = std::fs::read_to_string(&claude_md_path)?;
    let updated = content
        .lines()
        .filter(|line| !line.contains("@IRONMEM.md"))
        .collect::<Vec<_>>()
        .join("\n");

    std::fs::write(&claude_md_path, format!("{}\n", updated.trim_end()))?;
    Ok(())
}
