//! Unit tests for auth::login module
//!
//! Tests login requests, MFA requests, and token refresh request structures.

// Suppress false-positive unused_crate_dependencies warnings
// dev-dependencies are shared across ALL test targets in the crate
// This test may not use all deps, but they are required by other integration tests
#![allow(unused_crate_dependencies)]
#![allow(clippy::tests_outside_test_module, clippy::str_to_string, clippy::non_ascii_literal, clippy::shadow_unrelated, clippy::shadow_reuse, clippy::unwrap_used, clippy::expect_used, clippy::assertions_on_result_states, clippy::use_debug, clippy::let_underscore_must_use, clippy::string_add, clippy::string_add_assign, clippy::wildcard_enum_match_arm, clippy::unseparated_literal_suffix, clippy::indexing_slicing, clippy::doc_markdown, clippy::similar_names, clippy::impl_trait_in_params, unused_imports, dead_code, clippy::panic, clippy::redundant_clone)]

use fxt::auth::login::{LoginRequest, LoginResponse, MfaRequest, RefreshRequest, RefreshResponse};

/// Test LoginRequest creation
#[test]
fn test_login_request_creation() {
    let request = LoginRequest {
        username: "test_user".to_string(),
        password: "test_password".to_string(),
    };

    assert_eq!(request.username, "test_user");
    assert_eq!(request.password, "test_password");
}

/// Test LoginRequest serialization
#[test]
fn test_login_request_serialization() {
    let request = LoginRequest {
        username: "test_user".to_string(),
        password: "test_password".to_string(),
    };

    let json = serde_json::to_string(&request).unwrap();
    assert!(json.contains("test_user"));
    assert!(json.contains("test_password"));

    let deserialized: LoginRequest = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.username, request.username);
    assert_eq!(deserialized.password, request.password);
}

/// Test LoginRequest clone
#[test]
fn test_login_request_clone() {
    let request = LoginRequest {
        username: "test_user".to_string(),
        password: "test_password".to_string(),
    };

    let cloned = request.clone();
    assert_eq!(cloned.username, request.username);
    assert_eq!(cloned.password, request.password);
}

/// Test LoginResponse without MFA
#[test]
fn test_login_response_without_mfa() {
    let response = LoginResponse {
        access_token: "access_123".to_string(),
        refresh_token: "refresh_456".to_string(),
        expires_at: 1234567890,
        mfa_required: false,
        session_id: None,
    };

    assert!(!response.mfa_required);
    assert!(response.session_id.is_none());
}

/// Test LoginResponse with MFA
#[test]
fn test_login_response_with_mfa() {
    let response = LoginResponse {
        access_token: "temp_access".to_string(),
        refresh_token: "temp_refresh".to_string(),
        expires_at: 1234567890,
        mfa_required: true,
        session_id: Some("session_abc123".to_string()),
    };

    assert!(response.mfa_required);
    assert_eq!(response.session_id, Some("session_abc123".to_string()));
}

/// Test LoginResponse serialization
#[test]
fn test_login_response_serialization() {
    let response = LoginResponse {
        access_token: "access_123".to_string(),
        refresh_token: "refresh_456".to_string(),
        expires_at: 1234567890,
        mfa_required: true,
        session_id: Some("session_id".to_string()),
    };

    let json = serde_json::to_string(&response).unwrap();
    assert!(json.contains("access_123"));
    assert!(json.contains("refresh_456"));
    assert!(json.contains("session_id"));

    let deserialized: LoginResponse = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.access_token, response.access_token);
    assert_eq!(deserialized.mfa_required, response.mfa_required);
}

/// Test MfaRequest creation
#[test]
fn test_mfa_request_creation() {
    let request = MfaRequest {
        session_id: "session_abc123".to_string(),
        totp_code: "123456".to_string(),
    };

    assert_eq!(request.session_id, "session_abc123");
    assert_eq!(request.totp_code, "123456");
}

/// Test MfaRequest with different TOTP codes
#[test]
fn test_mfa_request_totp_codes() {
    let codes = vec!["000000", "123456", "999999", "654321"];

    for code in codes {
        let request = MfaRequest {
            session_id: "session_id".to_string(),
            totp_code: code.to_string(),
        };
        assert_eq!(request.totp_code, code);
    }
}

/// Test MfaRequest serialization
#[test]
fn test_mfa_request_serialization() {
    let request = MfaRequest {
        session_id: "session_abc123".to_string(),
        totp_code: "123456".to_string(),
    };

    let json = serde_json::to_string(&request).unwrap();
    assert!(json.contains("session_abc123"));
    assert!(json.contains("123456"));

    let deserialized: MfaRequest = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.session_id, request.session_id);
    assert_eq!(deserialized.totp_code, request.totp_code);
}

/// Test RefreshRequest creation
#[test]
fn test_refresh_request_creation() {
    let request = RefreshRequest {
        refresh_token: "refresh_token_abc123".to_string(),
    };

    assert_eq!(request.refresh_token, "refresh_token_abc123");
}

/// Test RefreshRequest serialization
#[test]
fn test_refresh_request_serialization() {
    let request = RefreshRequest {
        refresh_token: "refresh_token_abc123".to_string(),
    };

    let json = serde_json::to_string(&request).unwrap();
    assert!(json.contains("refresh_token_abc123"));

    let deserialized: RefreshRequest = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.refresh_token, request.refresh_token);
}

/// Test RefreshResponse without token rotation
#[test]
fn test_refresh_response_without_rotation() {
    let response = RefreshResponse {
        access_token: "new_access_token".to_string(),
        refresh_token: None,
        expires_at: 1234567890,
    };

    assert_eq!(response.access_token, "new_access_token");
    assert!(response.refresh_token.is_none());
}

/// Test RefreshResponse with token rotation
#[test]
fn test_refresh_response_with_rotation() {
    let response = RefreshResponse {
        access_token: "new_access_token".to_string(),
        refresh_token: Some("new_refresh_token".to_string()),
        expires_at: 1234567890,
    };

    assert_eq!(response.access_token, "new_access_token");
    assert_eq!(
        response.refresh_token,
        Some("new_refresh_token".to_string())
    );
}

/// Test RefreshResponse serialization
#[test]
fn test_refresh_response_serialization() {
    let response = RefreshResponse {
        access_token: "new_access_token".to_string(),
        refresh_token: Some("new_refresh_token".to_string()),
        expires_at: 1234567890,
    };

    let json = serde_json::to_string(&response).unwrap();
    assert!(json.contains("new_access_token"));
    assert!(json.contains("new_refresh_token"));

    let deserialized: RefreshResponse = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.access_token, response.access_token);
    assert_eq!(deserialized.refresh_token, response.refresh_token);
}

/// Test LoginRequest debug formatting
#[test]
fn test_login_request_debug() {
    let request = LoginRequest {
        username: "test_user".to_string(),
        password: "test_password".to_string(),
    };

    let debug_str = format!("{:?}", request);
    assert!(debug_str.contains("LoginRequest"));
}

/// Test LoginResponse debug formatting
#[test]
fn test_login_response_debug() {
    let response = LoginResponse {
        access_token: "access_123".to_string(),
        refresh_token: "refresh_456".to_string(),
        expires_at: 1234567890,
        mfa_required: false,
        session_id: None,
    };

    let debug_str = format!("{:?}", response);
    assert!(debug_str.contains("LoginResponse"));
}

/// Test MfaRequest clone
#[test]
fn test_mfa_request_clone() {
    let request = MfaRequest {
        session_id: "session_abc123".to_string(),
        totp_code: "123456".to_string(),
    };

    let cloned = request.clone();
    assert_eq!(cloned.session_id, request.session_id);
    assert_eq!(cloned.totp_code, request.totp_code);
}

/// Test RefreshRequest clone
#[test]
fn test_refresh_request_clone() {
    let request = RefreshRequest {
        refresh_token: "refresh_token_abc123".to_string(),
    };

    let cloned = request.clone();
    assert_eq!(cloned.refresh_token, request.refresh_token);
}

/// Test RefreshResponse clone
#[test]
fn test_refresh_response_clone() {
    let response = RefreshResponse {
        access_token: "new_access_token".to_string(),
        refresh_token: Some("new_refresh_token".to_string()),
        expires_at: 1234567890,
    };

    let cloned = response.clone();
    assert_eq!(cloned.access_token, response.access_token);
    assert_eq!(cloned.refresh_token, response.refresh_token);
    assert_eq!(cloned.expires_at, response.expires_at);
}

/// Test empty username validation
#[test]
fn test_empty_username() {
    let request = LoginRequest {
        username: "".to_string(),
        password: "password".to_string(),
    };

    assert!(request.username.is_empty());
}

/// Test empty password validation
#[test]
fn test_empty_password() {
    let request = LoginRequest {
        username: "user".to_string(),
        password: "".to_string(),
    };

    assert!(request.password.is_empty());
}

/// Test long username
#[test]
fn test_long_username() {
    let long_username = "a".repeat(1000);
    let request = LoginRequest {
        username: long_username.clone(),
        password: "password".to_string(),
    };

    assert_eq!(request.username.len(), 1000);
}

/// Test special characters in credentials
#[test]
fn test_special_characters_in_credentials() {
    let request = LoginRequest {
        username: "user@example.com".to_string(),
        password: "P@ssw0rd!123".to_string(),
    };

    assert!(request.username.contains('@'));
    assert!(request.password.contains('!'));
}
