//! Task filtering and sorting utilities for the dashboard
//!
//! Provides functionality to filter tasks by completion status, priority, type,
//! and search query, as well as sort by creation date, due date, or priority.

use crate::types::{ChecklistItemDto, TaskPriority, TaskType};

/// Sort options for tasks
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TaskSortOption {
    /// Sort by creation date (newest first)
    #[default]
    CreatedNewest,
    /// Sort by creation date (oldest first)
    CreatedOldest,
    /// Sort by priority (highest first)
    PriorityHighest,
    /// Sort by priority (lowest first)
    PriorityLowest,
    /// Sort by completion status (completed first)
    CompletedFirst,
    /// Sort by completion status (pending first)
    PendingFirst,
}

impl TaskSortOption {
    /// Get all available sort options
    pub fn all() -> &'static [Self] {
        &[
            Self::CreatedNewest,
            Self::CreatedOldest,
            Self::PriorityHighest,
            Self::PriorityLowest,
            Self::CompletedFirst,
            Self::PendingFirst,
        ]
    }

    /// Get display label for this sort option
    pub fn label(&self) -> &'static str {
        match self {
            Self::CreatedNewest => "Newest First",
            Self::CreatedOldest => "Oldest First",
            Self::PriorityHighest => "Highest Priority",
            Self::PriorityLowest => "Lowest Priority",
            Self::CompletedFirst => "Completed First",
            Self::PendingFirst => "Pending First",
        }
    }
}

/// Task filter criteria
#[derive(Debug, Clone, Default)]
pub struct TaskFilterCriteria {
    /// Filter by completion status: None = all, Some(true) = completed, Some(false) = pending
    pub completion_status: Option<bool>,
    /// Filter by priority
    pub priority: Option<TaskPriority>,
    /// Filter by task type
    pub task_type: Option<TaskType>,
    /// Search query for description or ID
    pub search_query: String,
    /// Sort order
    pub sort_order: TaskSortOption,
}

impl TaskFilterCriteria {
    /// Create a new filter criteria with all defaults
    pub fn new() -> Self {
        Self::default()
    }

    /// Set completion status filter
    pub fn with_completion_status(mut self, status: Option<bool>) -> Self {
        self.completion_status = status;
        self
    }

    /// Set priority filter
    pub fn with_priority(mut self, priority: Option<TaskPriority>) -> Self {
        self.priority = priority;
        self
    }

    /// Set task type filter
    pub fn with_task_type(mut self, task_type: Option<TaskType>) -> Self {
        self.task_type = task_type;
        self
    }

    /// Set search query
    pub fn with_search_query(mut self, query: impl Into<String>) -> Self {
        self.search_query = query.into();
        self
    }

    /// Set sort order
    pub fn with_sort_order(mut self, sort: TaskSortOption) -> Self {
        self.sort_order = sort;
        self
    }

    /// Apply filters and sorting to a list of tasks
    pub fn apply(&self, tasks: &[ChecklistItemDto]) -> Vec<ChecklistItemDto> {
        let mut filtered: Vec<_> = tasks
            .iter()
            .filter(|task| {
                // Apply completion status filter
                match self.completion_status {
                    Some(true) => task.completed,
                    Some(false) => !task.completed,
                    None => true, // Show all
                }
            })
            .filter(|task| {
                // Apply priority filter
                match self.priority {
                    Some(priority) => task.priority == priority,
                    None => true, // Show all
                }
            })
            .filter(|task| {
                // Apply task type filter
                match self.task_type {
                    Some(task_type) => task.task_type == task_type,
                    None => true, // Show all
                }
            })
            .filter(|task| {
                // Apply search query
                if self.search_query.is_empty() {
                    return true;
                }
                let query = self.search_query.to_lowercase();
                task.description.to_lowercase().contains(&query)
                    || task.id.to_lowercase().contains(&query)
                    || task.task_id.to_lowercase().contains(&query)
            })
            .cloned()
            .collect();

        // Apply sorting
        match self.sort_order {
            TaskSortOption::CreatedNewest => {
                filtered.sort_by(|a, b| b.created_at.cmp(&a.created_at));
            }
            TaskSortOption::CreatedOldest => {
                filtered.sort_by(|a, b| a.created_at.cmp(&b.created_at));
            }
            TaskSortOption::PriorityHighest => {
                filtered.sort_by(|a, b| {
                    let priority_order = |p: TaskPriority| match p {
                        TaskPriority::Critical => 0,
                        TaskPriority::High => 1,
                        TaskPriority::Medium => 2,
                        TaskPriority::Low => 3,
                    };
                    priority_order(a.priority).cmp(&priority_order(b.priority))
                });
            }
            TaskSortOption::PriorityLowest => {
                filtered.sort_by(|a, b| {
                    let priority_order = |p: TaskPriority| match p {
                        TaskPriority::Critical => 0,
                        TaskPriority::High => 1,
                        TaskPriority::Medium => 2,
                        TaskPriority::Low => 3,
                    };
                    priority_order(b.priority).cmp(&priority_order(a.priority))
                });
            }
            TaskSortOption::CompletedFirst => {
                filtered.sort_by(|a, b| b.completed.cmp(&a.completed));
            }
            TaskSortOption::PendingFirst => {
                filtered.sort_by(|a, b| a.completed.cmp(&b.completed));
            }
        }

        filtered
    }
}

/// Get task statistics from a list of tasks
#[derive(Debug)]
pub struct TaskStatistics {
    /// Total number of tasks
    pub total: usize,
    /// Number of completed tasks
    pub completed: usize,
    /// Number of pending tasks
    pub pending: usize,
    /// Completion percentage (0-100)
    pub completion_percentage: f64,
}

impl TaskStatistics {
    /// Calculate statistics from a list of tasks
    pub fn from_tasks(tasks: &[ChecklistItemDto]) -> Self {
        let total = tasks.len();
        let completed = tasks.iter().filter(|t| t.completed).count();
        let pending = total - completed;
        let completion_percentage = if total > 0 {
            (completed as f64 / total as f64) * 100.0
        } else {
            0.0
        };

        Self {
            total,
            completed,
            pending,
            completion_percentage,
        }
    }

    /// Count tasks by priority
    pub fn count_by_priority(tasks: &[ChecklistItemDto]) -> (usize, usize, usize, usize) {
        let critical = tasks
            .iter()
            .filter(|t| t.priority == TaskPriority::Critical)
            .count();
        let high = tasks
            .iter()
            .filter(|t| t.priority == TaskPriority::High)
            .count();
        let medium = tasks
            .iter()
            .filter(|t| t.priority == TaskPriority::Medium)
            .count();
        let low = tasks
            .iter()
            .filter(|t| t.priority == TaskPriority::Low)
            .count();
        (critical, high, medium, low)
    }

    /// Count tasks by type
    pub fn count_by_type(tasks: &[ChecklistItemDto]) -> [usize; 6] {
        [
            tasks
                .iter()
                .filter(|t| t.task_type == TaskType::Feature)
                .count(),
            tasks
                .iter()
                .filter(|t| t.task_type == TaskType::BugFix)
                .count(),
            tasks
                .iter()
                .filter(|t| t.task_type == TaskType::Documentation)
                .count(),
            tasks
                .iter()
                .filter(|t| t.task_type == TaskType::Testing)
                .count(),
            tasks
                .iter()
                .filter(|t| t.task_type == TaskType::Deployment)
                .count(),
            tasks
                .iter()
                .filter(|t| t.task_type == TaskType::Maintenance)
                .count(),
        ]
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn create_test_task(
        id: &str,
        description: &str,
        completed: bool,
        priority: TaskPriority,
    ) -> ChecklistItemDto {
        ChecklistItemDto {
            id: id.to_string(),
            task_id: format!("task_{}", id),
            description: description.to_string(),
            completed,
            completed_at: if completed {
                Some("2024-01-01".to_string())
            } else {
                None
            },
            created_at: "2024-01-01".to_string(),
            priority,
            task_type: TaskType::Feature,
        }
    }

    #[test]
    fn test_filter_by_completion_status() {
        let tasks = vec![
            create_test_task("1", "Completed task", true, TaskPriority::High),
            create_test_task("2", "Pending task", false, TaskPriority::Medium),
        ];

        let criteria = TaskFilterCriteria::new().with_completion_status(Some(true));
        let filtered = criteria.apply(&tasks);
        assert_eq!(filtered.len(), 1);
        assert!(filtered[0].completed);

        let criteria = TaskFilterCriteria::new().with_completion_status(Some(false));
        let filtered = criteria.apply(&tasks);
        assert_eq!(filtered.len(), 1);
        assert!(!filtered[0].completed);
    }

    #[test]
    fn test_filter_by_priority() {
        let tasks = vec![
            create_test_task("1", "High priority", false, TaskPriority::High),
            create_test_task("2", "Medium priority", false, TaskPriority::Medium),
            create_test_task("3", "Low priority", false, TaskPriority::Low),
        ];

        let criteria = TaskFilterCriteria::new().with_priority(Some(TaskPriority::High));
        let filtered = criteria.apply(&tasks);
        assert_eq!(filtered.len(), 1);
        assert_eq!(filtered[0].priority, TaskPriority::High);
    }

    #[test]
    fn test_search_query() {
        let tasks = vec![
            create_test_task("1", "Fix authentication bug", false, TaskPriority::High),
            create_test_task("2", "Add caching layer", false, TaskPriority::Medium),
        ];

        let criteria = TaskFilterCriteria::new().with_search_query("authentication");
        let filtered = criteria.apply(&tasks);
        assert_eq!(filtered.len(), 1);
        assert_eq!(filtered[0].description, "Fix authentication bug");
    }

    #[test]
    fn test_sort_by_priority() {
        let tasks = vec![
            create_test_task("1", "Low", false, TaskPriority::Low),
            create_test_task("2", "Critical", false, TaskPriority::Critical),
            create_test_task("3", "High", false, TaskPriority::High),
        ];

        let criteria = TaskFilterCriteria::new().with_sort_order(TaskSortOption::PriorityHighest);
        let sorted = criteria.apply(&tasks);

        assert_eq!(sorted[0].priority, TaskPriority::Critical);
        assert_eq!(sorted[1].priority, TaskPriority::High);
        assert_eq!(sorted[2].priority, TaskPriority::Low);
    }

    #[test]
    fn test_task_statistics() {
        let tasks = vec![
            create_test_task("1", "Task 1", true, TaskPriority::High),
            create_test_task("2", "Task 2", false, TaskPriority::Medium),
            create_test_task("3", "Task 3", true, TaskPriority::Low),
        ];

        let stats = TaskStatistics::from_tasks(&tasks);
        assert_eq!(stats.total, 3);
        assert_eq!(stats.completed, 2);
        assert_eq!(stats.pending, 1);
        assert!((stats.completion_percentage - 66.666).abs() < 0.1);
    }
}
