use lore::gitlab::types::{GitLabDiscussion, GitLabIssue};
use serde::de::DeserializeOwned;
use std::path::PathBuf;

fn load_fixture<T: DeserializeOwned>(name: &str) -> T {
    let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("tests/fixtures")
        .join(name);
    let content = std::fs::read_to_string(&path)
        .unwrap_or_else(|_| panic!("Failed to read fixture: {}", name));
    serde_json::from_str(&content)
        .unwrap_or_else(|e| panic!("Failed to parse fixture {}: {}", name, e))
}

#[test]
fn fixture_gitlab_issue_deserializes() {
    let issue: GitLabIssue = load_fixture("gitlab_issue.json");

    assert_eq!(issue.id, 12345);
    assert_eq!(issue.iid, 42);
    assert_eq!(issue.project_id, 100);
    assert_eq!(issue.title, "Test issue title");
    assert!(issue.description.is_some());
    assert_eq!(issue.state, "opened");
    assert_eq!(issue.author.username, "testuser");
    assert_eq!(issue.labels.len(), 2);
    assert!(issue.labels.contains(&"bug".to_string()));
}

#[test]
fn fixture_gitlab_issues_page_deserializes() {
    let issues: Vec<GitLabIssue> = load_fixture("gitlab_issues_page.json");

    assert!(
        issues.len() >= 3,
        "Need at least 3 issues for pagination tests"
    );

    assert!(!issues[0].labels.is_empty());

    assert!(issues[1].description.is_none());
    assert!(issues[1].labels.is_empty());

    assert!(issues[2].labels.len() >= 3);
}

#[test]
fn fixture_gitlab_discussion_deserializes() {
    let discussion: GitLabDiscussion = load_fixture("gitlab_discussion.json");

    assert_eq!(discussion.id, "6a9c1750b37d513a43987b574953fceb50b03ce7");
    assert!(!discussion.individual_note);
    assert!(discussion.notes.len() >= 2);
}

#[test]
fn fixture_gitlab_discussions_page_deserializes() {
    let discussions: Vec<GitLabDiscussion> = load_fixture("gitlab_discussions_page.json");

    assert!(
        discussions.len() >= 3,
        "Need multiple discussions for testing"
    );

    let has_individual = discussions.iter().any(|d| d.individual_note);
    let has_threaded = discussions.iter().any(|d| !d.individual_note);
    assert!(
        has_individual,
        "Need at least one individual_note=true discussion"
    );
    assert!(
        has_threaded,
        "Need at least one individual_note=false discussion"
    );
}

#[test]
fn fixture_has_system_note() {
    let discussion: GitLabDiscussion = load_fixture("gitlab_discussion.json");

    let has_system_note = discussion.notes.iter().any(|n| n.system);
    assert!(
        has_system_note,
        "Fixture should include at least one system note"
    );
}

#[test]
fn fixture_discussions_page_has_resolved_discussion() {
    let discussions: Vec<GitLabDiscussion> = load_fixture("gitlab_discussions_page.json");

    let has_resolved = discussions
        .iter()
        .any(|d| d.notes.iter().any(|n| n.resolved));
    assert!(has_resolved, "Should have at least one resolved discussion");
}
