use anyhow::Result;
use axum::extract::State;
use axum::response::Response;

use crate::db::Store;
use crate::model::Status;

use super::helpers::{error_response, list_projects_safe, render};
use super::AppState;

mod views;
use views::{IndexTemplate, ProjectCard};

/// Activity tier for sorting project cards on the index page.
/// Lower values sort first (most active projects at the top).
fn project_card_activity_tier(card: &ProjectCard) -> u32 {
    match card {
        ProjectCard::Ok {
            in_progress, open, ..
        } => {
            if *in_progress > 0 {
                0 // Has in-progress tasks
            } else if *open > 0 {
                1 // Has open tasks only
            } else {
                2 // Only closed or empty
            }
        }
        ProjectCard::Err { .. } => 3, // Error state
    }
}

pub(in crate::cmd::webui) async fn index_handler(State(state): State<AppState>) -> Response {
    let root = state.data_root.clone();
    let result = tokio::task::spawn_blocking(move || -> Result<IndexTemplate> {
        let projects = list_projects_safe(&root);
        let mut cards = Vec::with_capacity(projects.len());

        for name in &projects {
            match Store::open(&root, name) {
                Ok(store) => {
                    let tasks = store.list_tasks()?;
                    let open = tasks.iter().filter(|t| t.status == Status::Open).count();
                    let in_progress = tasks
                        .iter()
                        .filter(|t| t.status == Status::InProgress)
                        .count();
                    let closed = tasks.iter().filter(|t| t.status == Status::Closed).count();
                    cards.push(ProjectCard::Ok {
                        name: name.clone(),
                        open,
                        in_progress,
                        closed,
                        total: tasks.len(),
                    });
                }
                Err(e) => {
                    cards.push(ProjectCard::Err {
                        name: name.clone(),
                        error: format!("{e}"),
                    });
                }
            }
        }

        // Sort cards by activity tier, then by name alphabetically.
        cards.sort_by(|a, b| {
            let tier_a = project_card_activity_tier(a);
            let tier_b = project_card_activity_tier(b);
            match tier_a.cmp(&tier_b) {
                std::cmp::Ordering::Equal => {
                    let name_a = match a {
                        ProjectCard::Ok { name, .. } | ProjectCard::Err { name, .. } => name,
                    };
                    let name_b = match b {
                        ProjectCard::Ok { name, .. } | ProjectCard::Err { name, .. } => name,
                    };
                    name_a.cmp(name_b)
                }
                other => other,
            }
        });

        Ok(IndexTemplate {
            all_projects: projects,
            active_project: None,
            projects: cards,
        })
    })
    .await;

    match result {
        Ok(Ok(tmpl)) => render(tmpl),
        Ok(Err(e)) => error_response(500, &format!("{e}"), &[]),
        Err(e) => error_response(500, &format!("join error: {e}"), &[]),
    }
}
