use super::*;
use crate::gitlab::types::{GitLabAuthor, GitLabMilestone};

fn make_test_issue() -> GitLabIssue {
    GitLabIssue {
        id: 12345,
        iid: 42,
        project_id: 100,
        title: "Test issue".to_string(),
        description: Some("Description here".to_string()),
        state: "opened".to_string(),
        created_at: "2024-01-15T10:00:00.000Z".to_string(),
        updated_at: "2024-01-20T15:30:00.000Z".to_string(),
        closed_at: None,
        author: GitLabAuthor {
            id: 1,
            username: "testuser".to_string(),
            name: "Test User".to_string(),
        },
        assignees: vec![],
        labels: vec!["bug".to_string(), "priority::high".to_string()],
        milestone: None,
        due_date: None,
        web_url: "https://gitlab.example.com/group/project/-/issues/42".to_string(),
    }
}

#[test]
fn transforms_issue_with_all_fields() {
    let issue = make_test_issue();
    let result = transform_issue(&issue).unwrap();

    assert_eq!(result.issue.gitlab_id, 12345);
    assert_eq!(result.issue.iid, 42);
    assert_eq!(result.issue.project_id, 100);
    assert_eq!(result.issue.title, "Test issue");
    assert_eq!(
        result.issue.description,
        Some("Description here".to_string())
    );
    assert_eq!(result.issue.state, "opened");
    assert_eq!(result.issue.author_username, "testuser");
    assert_eq!(
        result.issue.web_url,
        "https://gitlab.example.com/group/project/-/issues/42"
    );
}

#[test]
fn handles_missing_description() {
    let mut issue = make_test_issue();
    issue.description = None;

    let result = transform_issue(&issue).unwrap();
    assert!(result.issue.description.is_none());
}

#[test]
fn extracts_label_names() {
    let issue = make_test_issue();
    let result = transform_issue(&issue).unwrap();

    assert_eq!(result.label_names.len(), 2);
    assert_eq!(result.label_names[0], "bug");
    assert_eq!(result.label_names[1], "priority::high");
}

#[test]
fn handles_empty_labels() {
    let mut issue = make_test_issue();
    issue.labels = vec![];

    let result = transform_issue(&issue).unwrap();
    assert!(result.label_names.is_empty());
}

#[test]
fn parses_timestamps_to_ms_epoch() {
    let issue = make_test_issue();
    let result = transform_issue(&issue).unwrap();

    assert_eq!(result.issue.created_at, 1705312800000);
    assert_eq!(result.issue.updated_at, 1705764600000);
}

#[test]
fn handles_timezone_offset_timestamps() {
    let mut issue = make_test_issue();
    issue.created_at = "2024-01-15T05:00:00-05:00".to_string();

    let result = transform_issue(&issue).unwrap();
    assert_eq!(result.issue.created_at, 1705312800000);
}

#[test]
fn extracts_assignee_usernames() {
    let mut issue = make_test_issue();
    issue.assignees = vec![
        GitLabAuthor {
            id: 2,
            username: "alice".to_string(),
            name: "Alice".to_string(),
        },
        GitLabAuthor {
            id: 3,
            username: "bob".to_string(),
            name: "Bob".to_string(),
        },
    ];

    let result = transform_issue(&issue).unwrap();
    assert_eq!(result.assignee_usernames.len(), 2);
    assert_eq!(result.assignee_usernames[0], "alice");
    assert_eq!(result.assignee_usernames[1], "bob");
}

#[test]
fn extracts_milestone_info() {
    let mut issue = make_test_issue();
    issue.milestone = Some(GitLabMilestone {
        id: 500,
        iid: 5,
        project_id: Some(100),
        title: "v1.0".to_string(),
        description: Some("First release".to_string()),
        state: Some("active".to_string()),
        due_date: Some("2024-02-01".to_string()),
        web_url: Some("https://gitlab.example.com/-/milestones/5".to_string()),
    });

    let result = transform_issue(&issue).unwrap();

    assert_eq!(result.issue.milestone_title, Some("v1.0".to_string()));

    let milestone = result.milestone.expect("should have milestone");
    assert_eq!(milestone.gitlab_id, 500);
    assert_eq!(milestone.iid, 5);
    assert_eq!(milestone.project_id, 100);
    assert_eq!(milestone.title, "v1.0");
    assert_eq!(milestone.description, Some("First release".to_string()));
    assert_eq!(milestone.state, Some("active".to_string()));
    assert_eq!(milestone.due_date, Some("2024-02-01".to_string()));
    assert_eq!(
        milestone.web_url,
        Some("https://gitlab.example.com/-/milestones/5".to_string())
    );
}

#[test]
fn handles_missing_milestone() {
    let issue = make_test_issue();
    let result = transform_issue(&issue).unwrap();

    assert!(result.issue.milestone_title.is_none());
    assert!(result.milestone.is_none());
}

#[test]
fn extracts_due_date() {
    let mut issue = make_test_issue();
    issue.due_date = Some("2024-02-15".to_string());

    let result = transform_issue(&issue).unwrap();
    assert_eq!(result.issue.due_date, Some("2024-02-15".to_string()));
}
