use chrono::NaiveDateTime;
use momentry_core::core::config;
use momentry_core::core::db::redis_client::ProcessorStatus;
use momentry_core::core::db::{JobErrorMessage, MonitorJobRedis, ProgressData, ProgressMessage};
use momentry_core::core::db::{MonitorJob, MonitorJobStats, MonitorJobStatus};

#[test]
fn test_config_database_url() {
    let url = config::DATABASE_URL.as_str();
    assert!(url.starts_with("postgres://"));
    assert!(url.contains("localhost"));
    assert!(url.contains("momentry"));
}

#[test]
fn test_config_redis_url() {
    let url = config::REDIS_URL.as_str();
    assert!(url.starts_with("redis://"));
    assert!(url.contains("localhost"));
}

#[test]
fn test_config_output_dir() {
    let dir = config::OUTPUT_DIR.as_str();
    assert!(dir.contains("momentry"));
}

#[test]
fn test_config_python_path() {
    let path = config::PYTHON_PATH.as_str();
    assert!(path.contains("python"));
}

#[test]
fn test_config_processor_timeouts() {
    assert!(*config::processor::ASR_TIMEOUT_SECS >= 60);
    assert!(*config::processor::CUT_TIMEOUT_SECS >= 60);
    assert!(*config::processor::DEFAULT_TIMEOUT_SECS >= 60);
}

#[test]
fn test_monitor_job_redis_serialization() {
    let job = MonitorJobRedis {
        uuid: "test-uuid-123".to_string(),
        status: "running".to_string(),
        current_processor: "asr".to_string(),
        progress_total: 100,
        progress_current: 50,
        error_count: 0,
        started_at: "2024-01-01T10:00:00Z".to_string(),
        updated_at: "2024-01-01T10:05:00Z".to_string(),
    };

    let json = serde_json::to_string(&job).unwrap();
    assert!(json.contains("test-uuid-123"));
    assert!(json.contains("running"));
}

#[test]
fn test_monitor_job_redis_deserialization() {
    let json = r#"{
        "uuid": "abc123",
        "status": "completed",
        "current_processor": "yolo",
        "progress_total": 100,
        "progress_current": 100,
        "error_count": 2,
        "started_at": "2024-01-01T10:00:00Z",
        "updated_at": "2024-01-01T10:30:00Z"
    }"#;

    let job: MonitorJobRedis = serde_json::from_str(json).unwrap();
    assert_eq!(job.uuid, "abc123");
    assert_eq!(job.status, "completed");
    assert_eq!(job.current_processor, "yolo");
}

#[test]
fn test_job_error_message_serialization() {
    let error = JobErrorMessage {
        uuid: "xyz789".to_string(),
        error: "Processing failed: invalid input".to_string(),
        timestamp: 1704067200,
    };

    let json = serde_json::to_string(&error).unwrap();
    assert!(json.contains("xyz789"));
    assert!(json.contains("Processing failed"));
}

#[test]
fn test_progress_message_serialization() {
    let progress = ProgressMessage {
        msg_type: "progress".to_string(),
        processor: "asr".to_string(),
        uuid: "test-uuid".to_string(),
        timestamp: 1704067200,
        data: ProgressData {
            message: Some("Processing segment 5".to_string()),
            current: Some(5),
            total: Some(100),
        },
    };

    let json = serde_json::to_string(&progress).unwrap();
    assert!(json.contains("progress"));
    assert!(json.contains("asr"));
}

#[test]
fn test_processor_status_serialization() {
    let status = ProcessorStatus {
        status: "running".to_string(),
        progress: 50,
        current: 50,
        total: 100,
        started_at: "2024-01-01T10:00:00Z".to_string(),
        updated_at: "2024-01-01T10:05:00Z".to_string(),
        message: "Processing".to_string(),
    };

    let json = serde_json::to_string(&status).unwrap();
    assert!(json.contains("running"));
    assert!(json.contains("50"));
}

#[test]
fn test_monitor_job_stats_serialization() {
    let stats = MonitorJobStats {
        pending: 5,
        running: 2,
        completed: 100,
        failed: 3,
    };

    let json = serde_json::to_string(&stats).unwrap();
    assert!(json.contains("\"pending\":5"));
    assert!(json.contains("\"completed\":100"));
}

#[test]
fn test_monitor_job_status_all_variants() {
    let statuses = vec![
        (MonitorJobStatus::Pending, "pending"),
        (MonitorJobStatus::Running, "running"),
        (MonitorJobStatus::Completed, "completed"),
        (MonitorJobStatus::Failed, "failed"),
        (MonitorJobStatus::Cancelled, "cancelled"),
    ];

    for (status, expected_str) in statuses {
        assert_eq!(status.as_str(), expected_str);
        assert_eq!(MonitorJobStatus::from_db_str(expected_str), Some(status));
    }
}

#[test]
fn test_monitor_job_status_roundtrip() {
    let original = MonitorJobStatus::Running;
    let json = serde_json::to_string(&original).unwrap();
    let parsed: MonitorJobStatus = serde_json::from_str(&json).unwrap();
    assert_eq!(original, parsed);
}

#[test]
fn test_monitor_job_full_roundtrip() {
    let original = MonitorJob {
        id: 42,
        uuid: "full-test-123".to_string(),
        video_path: Some("/path/to/video.mp4".to_string()),
        status: MonitorJobStatus::Running,
        current_processor: Some("ocr".to_string()),
        progress_total: 200,
        progress_current: 150,
        error_count: 1,
        last_error: Some("Minor warning".to_string()),
        started_at: Some(
            NaiveDateTime::parse_from_str("2024-01-01 10:00:00", "%Y-%m-%d %H:%M:%S").unwrap(),
        ),
        updated_at: Some(
            NaiveDateTime::parse_from_str("2024-01-01 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap(),
        ),
        created_at: NaiveDateTime::parse_from_str("2024-01-01 09:55:00", "%Y-%m-%d %H:%M:%S")
            .unwrap(),
    };

    let json = serde_json::to_string(&original).unwrap();
    let parsed: MonitorJob = serde_json::from_str(&json).unwrap();

    assert_eq!(parsed.id, original.id);
    assert_eq!(parsed.uuid, original.uuid);
    assert_eq!(parsed.status, original.status);
    assert_eq!(parsed.progress_current, original.progress_current);
    assert_eq!(parsed.error_count, original.error_count);
}
