use super::*;
use crate::core::error::LoreError;
use wiremock::matchers::{header, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};

#[tokio::test]
async fn get_issue_by_iid_success() {
    let server = MockServer::start().await;
    let issue_json = serde_json::json!({
        "id": 1001,
        "iid": 42,
        "project_id": 5,
        "title": "Fix login bug",
        "state": "opened",
        "created_at": "2026-01-15T10:00:00Z",
        "updated_at": "2026-02-01T14:30:00Z",
        "author": { "id": 1, "username": "dev1", "name": "Developer One" },
        "web_url": "https://gitlab.example.com/group/repo/-/issues/42",
        "labels": [],
        "milestone": null,
        "assignees": [],
        "closed_at": null,
        "description": "Login fails on mobile"
    });

    Mock::given(method("GET"))
        .and(path("/api/v4/projects/5/issues/42"))
        .and(header("PRIVATE-TOKEN", "test-token"))
        .respond_with(ResponseTemplate::new(200).set_body_json(&issue_json))
        .mount(&server)
        .await;

    let client = GitLabClient::new(&server.uri(), "test-token", Some(100.0));
    let issue = client.get_issue_by_iid(5, 42).await.unwrap();
    assert_eq!(issue.iid, 42);
    assert_eq!(issue.title, "Fix login bug");
}

#[tokio::test]
async fn get_issue_by_iid_not_found() {
    let server = MockServer::start().await;

    Mock::given(method("GET"))
        .and(path("/api/v4/projects/5/issues/999"))
        .respond_with(
            ResponseTemplate::new(404)
                .set_body_json(serde_json::json!({"message": "404 Not Found"})),
        )
        .mount(&server)
        .await;

    let client = GitLabClient::new(&server.uri(), "test-token", Some(100.0));
    let err = client.get_issue_by_iid(5, 999).await.unwrap_err();
    assert!(matches!(err, LoreError::GitLabNotFound { .. }));
}

#[tokio::test]
async fn get_mr_by_iid_success() {
    let server = MockServer::start().await;
    let mr_json = serde_json::json!({
        "id": 2001,
        "iid": 101,
        "project_id": 5,
        "title": "Add caching layer",
        "state": "merged",
        "created_at": "2026-01-20T09:00:00Z",
        "updated_at": "2026-02-10T16:00:00Z",
        "author": { "id": 2, "username": "dev2", "name": "Developer Two" },
        "web_url": "https://gitlab.example.com/group/repo/-/merge_requests/101",
        "source_branch": "feature/caching",
        "target_branch": "main",
        "draft": false,
        "labels": [],
        "milestone": null,
        "assignees": [],
        "reviewers": [],
        "merged_by": null,
        "merged_at": null,
        "closed_at": null,
        "description": "Adds Redis caching"
    });

    Mock::given(method("GET"))
        .and(path("/api/v4/projects/5/merge_requests/101"))
        .and(header("PRIVATE-TOKEN", "test-token"))
        .respond_with(ResponseTemplate::new(200).set_body_json(&mr_json))
        .mount(&server)
        .await;

    let client = GitLabClient::new(&server.uri(), "test-token", Some(100.0));
    let mr = client.get_mr_by_iid(5, 101).await.unwrap();
    assert_eq!(mr.iid, 101);
    assert_eq!(mr.title, "Add caching layer");
    assert_eq!(mr.source_branch, "feature/caching");
}

#[tokio::test]
async fn get_mr_by_iid_not_found() {
    let server = MockServer::start().await;

    Mock::given(method("GET"))
        .and(path("/api/v4/projects/5/merge_requests/999"))
        .respond_with(
            ResponseTemplate::new(404)
                .set_body_json(serde_json::json!({"message": "404 Not Found"})),
        )
        .mount(&server)
        .await;

    let client = GitLabClient::new(&server.uri(), "test-token", Some(100.0));
    let err = client.get_mr_by_iid(5, 999).await.unwrap_err();
    assert!(matches!(err, LoreError::GitLabNotFound { .. }));
}
