//! Tests for Timestamp sqlx integration.

use mad_hatter::Timestamp;
use sqlx::SqlitePool;

#[derive(Debug, sqlx::FromRow)]
struct TsRow {
    id: i32,
    created_at: Timestamp,
}

async fn setup_pool() -> SqlitePool {
    let pool = SqlitePool::connect("sqlite::memory:").await.unwrap();
    sqlx::query("CREATE TABLE test_timestamps (id INTEGER PRIMARY KEY, created_at TEXT NOT NULL)")
        .execute(&pool)
        .await
        .unwrap();
    pool
}

#[tokio::test]
async fn test_timestamp_insert_and_query_as_string() {
    let pool = setup_pool().await;
    let ts = Timestamp::parse("20260325121958").unwrap();

    sqlx::query("INSERT INTO test_timestamps (id, created_at) VALUES (?, ?)")
        .bind(1)
        .bind(&ts)
        .execute(&pool)
        .await
        .unwrap();

    let result: (i32, String) = sqlx::query_as("SELECT id, created_at FROM test_timestamps")
        .fetch_one(&pool)
        .await
        .unwrap();

    assert_eq!(result.0, 1);
    assert_eq!(result.1, "20260325121958");
}

#[tokio::test]
async fn test_timestamp_roundtrip() {
    let pool = setup_pool().await;
    let ts = Timestamp::parse("20260325121958").unwrap();

    sqlx::query("INSERT INTO test_timestamps (id, created_at) VALUES (?, ?)")
        .bind(1)
        .bind(&ts)
        .execute(&pool)
        .await
        .unwrap();

    let row: TsRow = sqlx::query_as("SELECT id, created_at FROM test_timestamps")
        .fetch_one(&pool)
        .await
        .unwrap();

    assert_eq!(row.id, 1);
    assert_eq!(row.created_at, ts);
    assert_eq!(row.created_at.as_str(), "20260325121958");
}

#[tokio::test]
async fn test_timestamp_roundtrip_multiple() {
    let pool = setup_pool().await;
    let ts1 = Timestamp::parse("20260101000000").unwrap();
    let ts2 = Timestamp::parse("20260630235959").unwrap();
    let ts3 = Timestamp::parse("20261231120000").unwrap();

    for (id, ts) in [(1, &ts1), (2, &ts2), (3, &ts3)] {
        sqlx::query("INSERT INTO test_timestamps (id, created_at) VALUES (?, ?)")
            .bind(id)
            .bind(ts)
            .execute(&pool)
            .await
            .unwrap();
    }

    let rows: Vec<TsRow> = sqlx::query_as("SELECT id, created_at FROM test_timestamps ORDER BY id")
        .fetch_all(&pool)
        .await
        .unwrap();

    assert_eq!(rows.len(), 3);
    assert_eq!(rows[0].created_at, ts1);
    assert_eq!(rows[1].created_at, ts2);
    assert_eq!(rows[2].created_at, ts3);
}

#[tokio::test]
async fn test_timestamp_update() {
    let pool = setup_pool().await;
    let ts1 = Timestamp::parse("20260101000000").unwrap();
    let ts2 = Timestamp::parse("20260325121958").unwrap();

    sqlx::query("INSERT INTO test_timestamps (id, created_at) VALUES (?, ?)")
        .bind(1)
        .bind(&ts1)
        .execute(&pool)
        .await
        .unwrap();

    sqlx::query("UPDATE test_timestamps SET created_at = ? WHERE id = ?")
        .bind(&ts2)
        .bind(1)
        .execute(&pool)
        .await
        .unwrap();

    let row: TsRow = sqlx::query_as("SELECT id, created_at FROM test_timestamps")
        .fetch_one(&pool)
        .await
        .unwrap();

    assert_eq!(row.created_at, ts2);
}

#[tokio::test]
async fn test_timestamp_filter() {
    let pool = setup_pool().await;
    let ts1 = Timestamp::parse("20260101000000").unwrap();
    let ts2 = Timestamp::parse("20260630235959").unwrap();

    sqlx::query("INSERT INTO test_timestamps (id, created_at) VALUES (?, ?)")
        .bind(1)
        .bind(&ts1)
        .execute(&pool)
        .await
        .unwrap();
    sqlx::query("INSERT INTO test_timestamps (id, created_at) VALUES (?, ?)")
        .bind(2)
        .bind(&ts2)
        .execute(&pool)
        .await
        .unwrap();

    let rows: Vec<TsRow> = sqlx::query_as("SELECT id, created_at FROM test_timestamps WHERE created_at = ?")
        .bind(&ts2)
        .fetch_all(&pool)
        .await
        .unwrap();

    assert_eq!(rows.len(), 1);
    assert_eq!(rows[0].id, 2);
    assert_eq!(rows[0].created_at, ts2);
}