// synops-tasks — Parse tasks.md og vis oppgavestatus.
//
// Leser tasks.md fra repo-roten og parser oppgaver med status,
// fase og detaljer. Støtter filtrering på fase og status.
//
// Output: formatert oppgaveliste til stdout.
//
// Ref: docs/retninger/unix_filosofi.md

use clap::Parser;
use regex::Regex;
use std::path::PathBuf;
use std::process;

/// Parse tasks.md og vis oppgavestatus.
#[derive(Parser)]
#[command(name = "synops-tasks", about = "Vis oppgavestatus fra tasks.md")]
struct Cli {
    /// Filtrer på fase (f.eks. 21 for "Fase 21")
    #[arg(long)]
    phase: Option<u32>,

    /// Filtrer på status: todo, done, blocked, inprogress, question, all
    #[arg(long, default_value = "all")]
    status: String,
}

#[derive(Debug, Clone)]
struct Task {
    phase: u32,
    phase_title: String,
    id: String,
    title: String,
    status: TaskStatus,
    details: Vec<String>,
}

#[derive(Debug, Clone, PartialEq)]
enum TaskStatus {
    Todo,
    InProgress,
    Done,
    Question,
    Blocked,
}

impl TaskStatus {
    fn symbol(&self) -> &str {
        match self {
            TaskStatus::Todo => "[ ]",
            TaskStatus::InProgress => "[~]",
            TaskStatus::Done => "[x]",
            TaskStatus::Question => "[?]",
            TaskStatus::Blocked => "[!]",
        }
    }

    fn label(&self) -> &str {
        match self {
            TaskStatus::Todo => "Klar",
            TaskStatus::InProgress => "Pågår",
            TaskStatus::Done => "Ferdig",
            TaskStatus::Question => "Spørsmål",
            TaskStatus::Blocked => "Blokkert",
        }
    }

    fn matches_filter(&self, filter: &str) -> bool {
        match filter {
            "all" => true,
            "todo" => *self == TaskStatus::Todo,
            "done" => *self == TaskStatus::Done,
            "blocked" => *self == TaskStatus::Blocked || *self == TaskStatus::Question,
            "inprogress" => *self == TaskStatus::InProgress,
            "question" => *self == TaskStatus::Question,
            _ => true,
        }
    }
}

fn find_tasks_md() -> Result<PathBuf, String> {
    // Prøv relativ sti først (repo-rot), deretter absolutt
    let candidates = [
        PathBuf::from("tasks.md"),
        PathBuf::from("/home/vegard/synops/tasks.md"),
    ];
    for path in &candidates {
        if path.exists() {
            return Ok(path.clone());
        }
    }
    Err("Fant ikke tasks.md (prøvde ./ og /home/vegard/synops/)".to_string())
}

fn parse_tasks(content: &str) -> Vec<Task> {
    let phase_re = Regex::new(r"^## Fase (\d+):\s*(.+)$").unwrap();
    let task_re = Regex::new(r"^- \[(.)\] (\d+\.\d+)\s+(.+)$").unwrap();
    let detail_re = Regex::new(r"^  > (.+)$").unwrap();

    let mut tasks = Vec::new();
    let mut current_phase: Option<(u32, String)> = None;

    for line in content.lines() {
        if let Some(caps) = phase_re.captures(line) {
            let num: u32 = caps[1].parse().unwrap_or(0);
            let title = caps[2].trim().to_string();
            current_phase = Some((num, title));
            continue;
        }

        if let Some(caps) = task_re.captures(line) {
            let status_char = &caps[1];
            let id = caps[2].to_string();
            let title = caps[3].to_string();

            let status = match status_char {
                " " => TaskStatus::Todo,
                "~" => TaskStatus::InProgress,
                "x" => TaskStatus::Done,
                "?" => TaskStatus::Question,
                "!" => TaskStatus::Blocked,
                _ => TaskStatus::Todo,
            };

            let (phase, phase_title) = current_phase
                .clone()
                .unwrap_or((0, "Ukjent".to_string()));

            tasks.push(Task {
                phase,
                phase_title,
                id,
                title,
                status,
                details: Vec::new(),
            });
            continue;
        }

        if let Some(caps) = detail_re.captures(line) {
            if let Some(task) = tasks.last_mut() {
                task.details.push(caps[1].to_string());
            }
        }
    }

    tasks
}

fn main() {
    let cli = Cli::parse();

    let valid_statuses = ["all", "todo", "done", "blocked", "inprogress", "question"];
    if !valid_statuses.contains(&cli.status.as_str()) {
        eprintln!(
            "Ugyldig status «{}». Gyldige verdier: {}",
            cli.status,
            valid_statuses.join(", ")
        );
        process::exit(1);
    }

    let path = match find_tasks_md() {
        Ok(p) => p,
        Err(e) => {
            eprintln!("Feil: {e}");
            process::exit(1);
        }
    };

    let content = match std::fs::read_to_string(&path) {
        Ok(c) => c,
        Err(e) => {
            eprintln!("Kunne ikke lese {}: {e}", path.display());
            process::exit(1);
        }
    };

    let tasks = parse_tasks(&content);

    // Filtrer
    let filtered: Vec<&Task> = tasks
        .iter()
        .filter(|t| {
            if let Some(phase) = cli.phase {
                if t.phase != phase {
                    return false;
                }
            }
            t.status.matches_filter(&cli.status)
        })
        .collect();

    if filtered.is_empty() {
        let mut msg = String::from("Ingen oppgaver funnet");
        if let Some(phase) = cli.phase {
            msg.push_str(&format!(" i fase {phase}"));
        }
        if cli.status != "all" {
            msg.push_str(&format!(" med status «{}»", cli.status));
        }
        println!("{msg}.");
        return;
    }

    // Grupper etter fase
    let mut current_phase: Option<u32> = None;

    // Sammendrag
    let total = filtered.len();
    let done = filtered.iter().filter(|t| t.status == TaskStatus::Done).count();
    let todo = filtered.iter().filter(|t| t.status == TaskStatus::Todo).count();
    let progress = filtered
        .iter()
        .filter(|t| t.status == TaskStatus::InProgress)
        .count();
    let blocked = filtered
        .iter()
        .filter(|t| t.status == TaskStatus::Blocked || t.status == TaskStatus::Question)
        .count();

    if let Some(phase) = cli.phase {
        println!("# Fase {phase}\n");
    } else {
        println!("# Oppgavestatus\n");
    }

    println!(
        "Totalt: {total}  |  Ferdig: {done}  |  Klar: {todo}  |  Pågår: {progress}  |  Blokkert: {blocked}\n"
    );

    for task in &filtered {
        if current_phase != Some(task.phase) {
            current_phase = Some(task.phase);
            println!("## Fase {}: {}\n", task.phase, task.phase_title);
        }

        println!(
            "  {} {} {}",
            task.status.symbol(),
            task.id,
            task.title
        );

        // Vis statuslabel for ikke-ferdige oppgaver
        if task.status != TaskStatus::Done {
            println!("      Status: {}", task.status.label());
        }

        for detail in &task.details {
            println!("      > {detail}");
        }
    }

    // Fremdriftsbar for filtrert sett
    if total > 0 {
        let pct = (done as f64 / total as f64 * 100.0) as u32;
        let bar_width = 30;
        let filled = (pct as usize * bar_width) / 100;
        let empty = bar_width - filled;
        println!(
            "\nFremdrift: [{}{}] {pct}% ({done}/{total})",
            "█".repeat(filled),
            "░".repeat(empty)
        );
    }
}
