use crate::model::Task;

/// Columns the task table can be sorted by.
#[derive(Clone, Copy, PartialEq, Eq)]
pub(in crate::cmd::webui) enum SortField {
    Id,
    Status,
    Type,
    Priority,
    Effort,
    Title,
    Created,
}

impl SortField {
    pub(in crate::cmd::webui) fn parse(s: &str) -> Option<Self> {
        match s {
            "id" => Some(Self::Id),
            "status" => Some(Self::Status),
            "type" => Some(Self::Type),
            "priority" => Some(Self::Priority),
            "effort" => Some(Self::Effort),
            "title" => Some(Self::Title),
            "created" => Some(Self::Created),
            _ => None,
        }
    }

    pub(in crate::cmd::webui) fn as_str(self) -> &'static str {
        match self {
            Self::Id => "id",
            Self::Status => "status",
            Self::Type => "type",
            Self::Priority => "priority",
            Self::Effort => "effort",
            Self::Title => "title",
            Self::Created => "created",
        }
    }

    /// Sensible default direction when the user first clicks a column.
    pub(in crate::cmd::webui) fn default_order(self) -> SortOrder {
        match self {
            // Newest first, alphabetical ascending for text fields.
            Self::Created => SortOrder::Desc,
            Self::Title | Self::Id | Self::Type => SortOrder::Asc,
            // Highest priority/effort first; open before closed.
            Self::Priority | Self::Effort | Self::Status => SortOrder::Asc,
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub(in crate::cmd::webui) enum SortOrder {
    Asc,
    Desc,
}

impl SortOrder {
    pub(in crate::cmd::webui) fn parse(s: &str) -> Option<Self> {
        match s {
            "asc" => Some(Self::Asc),
            "desc" => Some(Self::Desc),
            _ => None,
        }
    }

    pub(in crate::cmd::webui) fn as_str(self) -> &'static str {
        match self {
            Self::Asc => "asc",
            Self::Desc => "desc",
        }
    }
}

/// Map a `Status` to a numeric value for semantic sorting.
/// Lower values sort first in ascending order: open → in_progress → closed.
fn status_sort_key(s: crate::model::Status) -> i32 {
    match s {
        crate::model::Status::Open => 1,
        crate::model::Status::InProgress => 2,
        crate::model::Status::Closed => 3,
    }
}

/// Apply the chosen sort field and direction to a filtered task list.
pub(in crate::cmd::webui) fn sort_tasks(tasks: &mut [&Task], field: SortField, order: SortOrder) {
    tasks.sort_by(|a, b| {
        let cmp = match field {
            SortField::Id => a.id.as_str().cmp(b.id.as_str()),
            SortField::Status => status_sort_key(a.status).cmp(&status_sort_key(b.status)),
            SortField::Type => a.task_type.cmp(&b.task_type),
            SortField::Priority => a.priority.score().cmp(&b.priority.score()),
            SortField::Effort => a.effort.score().cmp(&b.effort.score()),
            SortField::Title => a
                .title
                .to_ascii_lowercase()
                .cmp(&b.title.to_ascii_lowercase()),
            SortField::Created => a.created_at.cmp(&b.created_at),
        };
        match order {
            SortOrder::Asc => cmp,
            SortOrder::Desc => cmp.reverse(),
        }
    });
}
