use crate::types::ScrollStatus;
use super::types::ExternalSystem;

/// Maps FURNACE scroll statuses to/from external system statuses.
pub struct StatusMapper;

impl StatusMapper {
    /// Convert a FURNACE `ScrollStatus` to the corresponding status string in
    /// the given external system.
    pub fn furnace_to_external(status: &ScrollStatus, system: &ExternalSystem) -> String {
        match system {
            ExternalSystem::Linear => match status {
                ScrollStatus::Draft => "backlog".to_string(),
                ScrollStatus::Validated => "ready".to_string(),
                ScrollStatus::InProgress => "in_progress".to_string(),
                ScrollStatus::Completed => "done".to_string(),
                ScrollStatus::Failed => "cancelled".to_string(),
                ScrollStatus::Archived => "done".to_string(),
            },
            ExternalSystem::Jira => match status {
                ScrollStatus::Draft => "To Do".to_string(),
                ScrollStatus::Validated => "Selected for Development".to_string(),
                ScrollStatus::InProgress => "In Progress".to_string(),
                ScrollStatus::Completed => "Done".to_string(),
                ScrollStatus::Failed => "Won't Do".to_string(),
                ScrollStatus::Archived => "Done".to_string(),
            },
            ExternalSystem::Notion => match status {
                ScrollStatus::Draft => "Not Started".to_string(),
                ScrollStatus::Validated => "Not Started".to_string(),
                ScrollStatus::InProgress => "In Progress".to_string(),
                ScrollStatus::Completed => "Done".to_string(),
                ScrollStatus::Failed => "Not Started".to_string(),
                ScrollStatus::Archived => "Done".to_string(),
            },
        }
    }

    /// Convert an external status string back to a FURNACE `ScrollStatus`.
    ///
    /// The mapping is best-effort: unknown strings default to `Draft`.
    pub fn external_to_furnace(status: &str) -> ScrollStatus {
        match status {
            // Linear
            "backlog" => ScrollStatus::Draft,
            "ready" => ScrollStatus::Validated,
            "in_progress" => ScrollStatus::InProgress,
            "done" => ScrollStatus::Completed,
            "cancelled" => ScrollStatus::Failed,

            // Jira
            "To Do" => ScrollStatus::Draft,
            "Selected for Development" => ScrollStatus::Validated,
            "In Progress" => ScrollStatus::InProgress,
            "Done" => ScrollStatus::Completed,
            "Won't Do" => ScrollStatus::Failed,

            // Notion
            "Not Started" => ScrollStatus::Draft,

            // Unknown
            _ => ScrollStatus::Draft,
        }
    }
}

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

    #[test]
    fn test_linear_round_trip() {
        let sys = ExternalSystem::Linear;
        let statuses = [
            ScrollStatus::Draft,
            ScrollStatus::Validated,
            ScrollStatus::InProgress,
            ScrollStatus::Completed,
            ScrollStatus::Failed,
        ];

        for status in &statuses {
            let ext = StatusMapper::furnace_to_external(status, &sys);
            let back = StatusMapper::external_to_furnace(&ext);
            assert_eq!(
                &back, status,
                "Linear round-trip failed for {:?} -> {} -> {:?}",
                status, ext, back
            );
        }
    }

    #[test]
    fn test_jira_round_trip() {
        let sys = ExternalSystem::Jira;
        let statuses = [
            ScrollStatus::Draft,
            ScrollStatus::Validated,
            ScrollStatus::InProgress,
            ScrollStatus::Completed,
            ScrollStatus::Failed,
        ];

        for status in &statuses {
            let ext = StatusMapper::furnace_to_external(status, &sys);
            let back = StatusMapper::external_to_furnace(&ext);
            assert_eq!(
                &back, status,
                "Jira round-trip failed for {:?} -> {} -> {:?}",
                status, ext, back
            );
        }
    }

    #[test]
    fn test_notion_forward_mapping() {
        let sys = ExternalSystem::Notion;
        assert_eq!(
            StatusMapper::furnace_to_external(&ScrollStatus::Draft, &sys),
            "Not Started"
        );
        assert_eq!(
            StatusMapper::furnace_to_external(&ScrollStatus::InProgress, &sys),
            "In Progress"
        );
        assert_eq!(
            StatusMapper::furnace_to_external(&ScrollStatus::Completed, &sys),
            "Done"
        );
    }

    #[test]
    fn test_notion_reverse_mapping() {
        assert_eq!(
            StatusMapper::external_to_furnace("Not Started"),
            ScrollStatus::Draft
        );
        assert_eq!(
            StatusMapper::external_to_furnace("In Progress"),
            ScrollStatus::InProgress
        );
        assert_eq!(
            StatusMapper::external_to_furnace("Done"),
            ScrollStatus::Completed
        );
    }

    #[test]
    fn test_unknown_external_status_defaults_to_draft() {
        assert_eq!(
            StatusMapper::external_to_furnace("something_unknown"),
            ScrollStatus::Draft
        );
    }

    #[test]
    fn test_archived_maps_to_done() {
        for sys in &[ExternalSystem::Linear, ExternalSystem::Jira, ExternalSystem::Notion] {
            let ext = StatusMapper::furnace_to_external(&ScrollStatus::Archived, sys);
            assert!(
                ext == "done" || ext == "Done",
                "Archived should map to done/Done for {:?}, got {}",
                sys,
                ext
            );
        }
    }
}
