//! Tests for commit module

use chrono::Utc;
use governor_core::domain::commit::{Commit, CommitHistory, CommitType};

#[test]
fn test_commit_creation() {
    let commit = Commit::new(
        "abc123def".to_string(),
        "feat(api): add new endpoint".to_string(),
        "Author".to_string(),
        "author@example.com".to_string(),
        Utc::now(),
    );
    assert_eq!(commit.hash, "abc123def");
    assert_eq!(commit.short_hash, "abc123d");
    assert_eq!(commit.commit_type(), Some(CommitType::Feat));
    assert_eq!(commit.scope, Some("api".to_string()));
    assert!(commit.affects_scope("api"));
}

#[test]
fn test_conventional_commit_parsing() {
    let commit = Commit::new(
        "abc123".to_string(),
        "feat(api): add new endpoint".to_string(),
        "Author".to_string(),
        "author@example.com".to_string(),
        Utc::now(),
    );
    assert_eq!(commit.commit_type(), Some(CommitType::Feat));
    assert_eq!(commit.scope, Some("api".to_string()));
    assert!(commit.affects_scope("api"));
}

#[test]
fn test_breaking_commit_parsing() {
    let commit = Commit::new(
        "abc123".to_string(),
        "feat!: redesign with modular architecture".to_string(),
        "Author".to_string(),
        "author@example.com".to_string(),
        Utc::now(),
    );
    assert_eq!(commit.commit_type(), Some(CommitType::Feat));
    assert!(commit.breaking);
}

#[test]
fn test_non_conventional_commit() {
    let commit = Commit::new(
        "abc123".to_string(),
        "Add some stuff".to_string(),
        "Author".to_string(),
        "author@example.com".to_string(),
        Utc::now(),
    );
    assert_eq!(commit.commit_type(), None);
    assert!(!commit.is_conventional());
}

#[test]
fn test_scope_parsing() {
    let commit = Commit::new(
        "abc123".to_string(),
        "feat(api): add new endpoint".to_string(),
        "Author".to_string(),
        "author@example.com".to_string(),
        Utc::now(),
    );
    assert_eq!(commit.commit_type(), Some(CommitType::Feat));
    assert_eq!(commit.scope, Some("api".to_string()));
    assert!(commit.affects_scope("api"));
}

#[test]
fn test_commit_history_filtering() {
    let commits = vec![
        Commit::new(
            "1".to_string(),
            "feat: new feature".to_string(),
            "A".to_string(),
            "a@a.com".to_string(),
            Utc::now(),
        ),
        Commit::new(
            "2".to_string(),
            "chore: update deps".to_string(),
            "A".to_string(),
            "a@a.com".to_string(),
            Utc::now(),
        ),
        Commit::new(
            "3".to_string(),
            "fix: bug fix".to_string(),
            "A".to_string(),
            "a@a.com".to_string(),
            Utc::now(),
        ),
    ];

    let history = CommitHistory::new(commits);
    let filtered = history.by_type(CommitType::Feat);
    assert_eq!(filtered.len(), 1);
}

#[test]
fn test_commit_type_is_breaking() {
    assert!(CommitType::Feat.is_breaking());
    assert!(CommitType::Fix.is_breaking());
    assert!(CommitType::Perf.is_breaking());
    assert!(CommitType::Refactor.is_breaking());
    assert!(!CommitType::Docs.is_breaking());
    assert!(!CommitType::Style.is_breaking());
}

#[test]
fn test_commit_type_is_feature() {
    assert!(CommitType::Feat.is_feature());
    assert!(!CommitType::Fix.is_feature());
}

#[test]
fn test_commit_type_is_fix() {
    assert!(CommitType::Fix.is_fix());
    assert!(CommitType::Perf.is_fix());
    assert!(!CommitType::Feat.is_fix());
}

#[test]
fn test_commit_type_is_changeloggable() {
    assert!(CommitType::Feat.is_changeloggable());
    assert!(CommitType::Fix.is_changeloggable());
    assert!(!CommitType::Docs.is_changeloggable());
    assert!(!CommitType::Style.is_changeloggable());
}

#[test]
fn test_short_message() {
    let commit = Commit::new(
        "abc123".to_string(),
        "feat(api): add new endpoint\n\nThis is a longer description".to_string(),
        "Author".to_string(),
        "author@example.com".to_string(),
        Utc::now(),
    );
    assert_eq!(commit.short_message(), "feat(api): add new endpoint");
}

#[test]
fn test_commit_type_parse_from_str() {
    assert_eq!(CommitType::parse_from_str("feat"), Some(CommitType::Feat));
    assert_eq!(CommitType::parse_from_str("fix"), Some(CommitType::Fix));
    assert_eq!(CommitType::parse_from_str("FEAT"), Some(CommitType::Feat));
    assert_eq!(CommitType::parse_from_str("unknown"), None);
}

#[test]
fn test_commit_type_display() {
    assert_eq!(CommitType::Feat.to_string(), "feat");
    assert_eq!(CommitType::Fix.to_string(), "fix");
    assert_eq!(CommitType::Docs.to_string(), "docs");
}

#[test]
fn test_is_type() {
    let commit = Commit::new(
        "abc123".to_string(),
        "feat: new feature".to_string(),
        "Author".to_string(),
        "author@example.com".to_string(),
        Utc::now(),
    );
    assert!(commit.is_type(CommitType::Feat));
    assert!(!commit.is_type(CommitType::Fix));
}
