use anyhow::Result;
use comfy_table::presets::NOTHING;
use comfy_table::{Cell, Table};
use std::path::Path;

use crate::color::{cell_bold, cell_effort, cell_priority, cell_status, stdout_use_color};
use crate::db;
use crate::model::{Effort, Priority, Status};

pub struct Opts<'a> {
    pub status: Option<&'a str>,
    pub priority: Option<Priority>,
    pub effort: Option<Effort>,
    pub label: Option<&'a str>,
    pub task_type: Option<&'a str>,
    pub all: bool,
    pub json: bool,
}

pub fn run(root: &Path, opts: Opts) -> Result<()> {
    let store = db::open(root)?;
    let mut tasks = store.list_tasks()?;

    if let Some(s) = opts.status {
        let parsed = Status::parse(s)?;
        tasks.retain(|t| t.status == parsed);
    } else if !opts.all {
        // By default, show open and in-progress tasks but not closed.
        tasks.retain(|t| t.status == Status::Open || t.status == Status::InProgress);
    }
    if let Some(p) = opts.priority {
        tasks.retain(|t| t.priority == p);
    }
    if let Some(e) = opts.effort {
        tasks.retain(|t| t.effort == e);
    }
    if let Some(l) = opts.label {
        tasks.retain(|t| t.labels.iter().any(|x| x == l));
    }
    if let Some(tt) = opts.task_type {
        tasks.retain(|t| t.task_type == tt);
    }

    tasks.sort_by_key(|t| (t.priority.score(), t.created_at.clone()));

    if opts.json {
        // Keep list JSON lean: include scheduling fields but not full work-log history.
        let mut value = serde_json::to_value(&tasks)?;
        if let Some(items) = value.as_array_mut() {
            for item in items {
                if let Some(obj) = item.as_object_mut() {
                    obj.remove("logs");
                }
            }
        }
        println!("{}", serde_json::to_string(&value)?);
    } else {
        let use_color = stdout_use_color();
        let mut table = Table::new();
        table.load_preset(NOTHING);
        table.set_header(vec![
            "ID", "STATUS", "TYPE", "PRIORITY", "EFFORT", "LABELS", "TITLE",
        ]);
        for t in &tasks {
            table.add_row(vec![
                cell_bold(&t.id, use_color),
                cell_status(format!("[{}]", t.status.as_str()), t.status, use_color),
                Cell::new(&t.task_type),
                cell_priority(t.priority.as_str(), t.priority, use_color),
                cell_effort(t.effort.as_str(), t.effort, use_color),
                Cell::new(t.labels.join(", ")),
                Cell::new(&t.title),
            ]);
        }
        if !tasks.is_empty() {
            println!("{table}");
        }
    }

    Ok(())
}
