use event_integration_test::user_event::use_localhost_af_cloud;
use event_integration_test::EventIntegrationTest;
use flowy_ai_pub::cloud::MessageCursor;
use flowy_ai_pub::persistence::{
  select_answer_where_match_reply_message_id, select_chat_messages, select_message,
  select_message_content, total_message_count, upsert_chat_messages, ChatMessageTable,
};
use uuid::Uuid;

#[tokio::test]
async fn chat_message_table_insert_select_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();
  let message_id_1 = 1000;
  let message_id_2 = 2000;

  // Create test messages
  let messages = vec![
    ChatMessageTable {
      message_id: message_id_1,
      chat_id: chat_id.clone(),
      content: "Hello, this is a test message".to_string(),
      created_at: 1625097600, // 2021-07-01
      author_type: 1,         // User
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
    ChatMessageTable {
      message_id: message_id_2,
      chat_id: chat_id.clone(),
      content: "This is a reply to the test message".to_string(),
      created_at: 1625097700, // 2021-07-01, 100 seconds later
      author_type: 0,         // AI
      author_id: "ai".to_string(),
      reply_message_id: Some(message_id_1),
      metadata: Some(r#"{"source": "test"}"#.to_string()),
      is_sync: false,
    },
  ];

  // Test insert_chat_messages
  let result = upsert_chat_messages(db_conn, &messages);
  assert!(
    result.is_ok(),
    "Failed to insert chat messages: {:?}",
    result
  );

  // Test select_chat_messages
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let messages_result =
    select_chat_messages(db_conn, &chat_id, 10, MessageCursor::Offset(0)).unwrap();

  assert_eq!(messages_result.messages.len(), 2);
  assert_eq!(messages_result.total_count, 2);
  assert!(!messages_result.has_more);

  // Verify the content of the returned messages
  let first_message = messages_result
    .messages
    .iter()
    .find(|m| m.message_id == message_id_1)
    .unwrap();
  assert_eq!(first_message.content, "Hello, this is a test message");
  assert_eq!(first_message.author_type, 1);

  let second_message = messages_result
    .messages
    .iter()
    .find(|m| m.message_id == message_id_2)
    .unwrap();
  assert_eq!(
    second_message.content,
    "This is a reply to the test message"
  );
  assert_eq!(second_message.reply_message_id, Some(message_id_1));
}

#[tokio::test]
async fn chat_message_table_cursor_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();

  // Create multiple test messages with sequential IDs
  let mut messages = Vec::new();
  for i in 1..6 {
    messages.push(ChatMessageTable {
      message_id: i * 1000,
      chat_id: chat_id.clone(),
      content: format!("Message {}", i),
      created_at: 1625097600 + (i * 100), // Increasing timestamps
      author_type: 1,                     // User
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    });
  }

  // Insert messages
  upsert_chat_messages(db_conn, &messages).unwrap();

  // Test MessageCursor::Offset
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_offset = select_chat_messages(
    db_conn,
    &chat_id,
    2, // Limit to 2 messages
    MessageCursor::Offset(0),
  )
  .unwrap();

  assert_eq!(result_offset.messages.len(), 2);
  assert!(result_offset.has_more);

  // Test MessageCursor::AfterMessageId
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_after = select_chat_messages(
    db_conn,
    &chat_id,
    3, // Limit to 3 messages
    MessageCursor::AfterMessageId(2000),
  )
  .unwrap();

  assert_eq!(result_after.messages.len(), 3); // Should get message IDs 3000, 4000, 5000
  assert!(result_after.messages.iter().all(|m| m.message_id > 2000));

  // Test MessageCursor::BeforeMessageId
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_before = select_chat_messages(
    db_conn,
    &chat_id,
    2, // Limit to 2 messages
    MessageCursor::BeforeMessageId(4000),
  )
  .unwrap();

  assert_eq!(result_before.messages.len(), 2); // Should get message IDs 1000, 2000, 3000
  assert!(result_before.messages.iter().all(|m| m.message_id < 4000));
}

#[tokio::test]
async fn chat_message_total_count_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();

  // Create test messages
  let messages = vec![
    ChatMessageTable {
      message_id: 1001,
      chat_id: chat_id.clone(),
      content: "Message 1".to_string(),
      created_at: 1625097600,
      author_type: 1,
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
    ChatMessageTable {
      message_id: 1002,
      chat_id: chat_id.clone(),
      content: "Message 2".to_string(),
      created_at: 1625097700,
      author_type: 0,
      author_id: "ai".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
  ];

  // Insert messages
  upsert_chat_messages(db_conn, &messages).unwrap();

  // Test total_message_count
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let count = total_message_count(db_conn, &chat_id).unwrap();
  assert_eq!(count, 2);

  // Add one more message
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let additional_message = ChatMessageTable {
    message_id: 1003,
    chat_id: chat_id.clone(),
    content: "Message 3".to_string(),
    created_at: 1625097800,
    author_type: 1,
    author_id: "user_1".to_string(),
    reply_message_id: None,
    metadata: None,
    is_sync: false,
  };

  upsert_chat_messages(db_conn, &[additional_message]).unwrap();

  // Verify count increased
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let updated_count = total_message_count(db_conn, &chat_id).unwrap();
  assert_eq!(updated_count, 3);

  // Test count for non-existent chat
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let empty_count = total_message_count(db_conn, "non_existent_chat").unwrap();
  assert_eq!(empty_count, 0);
}

#[tokio::test]
async fn chat_message_select_message_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();
  let message_id = 2001;

  // Create test message
  let message = ChatMessageTable {
    message_id,
    chat_id: chat_id.clone(),
    content: "This is a test message for select_message".to_string(),
    created_at: 1625097600,
    author_type: 1,
    author_id: "user_1".to_string(),
    reply_message_id: None,
    metadata: Some(r#"{"test_key": "test_value"}"#.to_string()),
    is_sync: false,
  };

  // Insert message
  upsert_chat_messages(db_conn, &[message]).unwrap();

  // Test select_message
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result = select_message(db_conn, message_id).unwrap();
  assert!(result.is_some());

  let retrieved_message = result.unwrap();
  assert_eq!(retrieved_message.message_id, message_id);
  assert_eq!(retrieved_message.chat_id, chat_id);
  assert_eq!(
    retrieved_message.content,
    "This is a test message for select_message"
  );
  assert_eq!(retrieved_message.author_id, "user_1");
  assert_eq!(
    retrieved_message.metadata,
    Some(r#"{"test_key": "test_value"}"#.to_string())
  );

  // Test select_message with non-existent ID
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let non_existent = select_message(db_conn, 9999).unwrap();
  assert!(non_existent.is_none());
}

#[tokio::test]
async fn chat_message_select_content_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();
  let message_id = 3001;
  let message_content = "This is the content to retrieve";

  // Create test message
  let message = ChatMessageTable {
    message_id,
    chat_id: chat_id.clone(),
    content: message_content.to_string(),
    created_at: 1625097600,
    author_type: 1,
    author_id: "user_1".to_string(),
    reply_message_id: None,
    metadata: None,
    is_sync: false,
  };

  // Insert message
  upsert_chat_messages(db_conn, &[message]).unwrap();

  // Test select_message_content
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let content = select_message_content(db_conn, message_id).unwrap();
  assert!(content.is_some());
  assert_eq!(content.unwrap(), message_content);

  // Test with non-existent message
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let no_content = select_message_content(db_conn, 9999).unwrap();
  assert!(no_content.is_none());
}

#[tokio::test]
async fn chat_message_reply_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();
  let question_id = 4001;
  let answer_id = 4002;

  // Create question and answer messages
  let question = ChatMessageTable {
    message_id: question_id,
    chat_id: chat_id.clone(),
    content: "What is the question?".to_string(),
    created_at: 1625097600,
    author_type: 1, // User
    author_id: "user_1".to_string(),
    reply_message_id: None,
    metadata: None,
    is_sync: false,
  };

  let answer = ChatMessageTable {
    message_id: answer_id,
    chat_id: chat_id.clone(),
    content: "This is the answer".to_string(),
    created_at: 1625097700,
    author_type: 0, // AI
    author_id: "ai".to_string(),
    reply_message_id: Some(question_id), // Link to question
    metadata: None,
    is_sync: false,
  };

  // Insert messages
  upsert_chat_messages(db_conn, &[question, answer]).unwrap();

  // Test select_message_where_match_reply_message_id
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result = select_answer_where_match_reply_message_id(db_conn, &chat_id, question_id).unwrap();

  assert!(result.is_some());
  let reply = result.unwrap();
  assert_eq!(reply.message_id, answer_id);
  assert_eq!(reply.content, "This is the answer");
  assert_eq!(reply.reply_message_id, Some(question_id));

  // Test with non-existent reply relation
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let no_reply = select_answer_where_match_reply_message_id(
    db_conn, &chat_id, 9999, // Non-existent question ID
  )
  .unwrap();

  assert!(no_reply.is_none());

  // Test with wrong chat_id
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let wrong_chat =
    select_answer_where_match_reply_message_id(db_conn, "wrong_chat_id", question_id).unwrap();

  assert!(wrong_chat.is_none());
}

#[tokio::test]
async fn chat_message_upsert_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();
  let message_id = 5001;

  // Create initial message
  let message = ChatMessageTable {
    message_id,
    chat_id: chat_id.clone(),
    content: "Original content".to_string(),
    created_at: 1625097600,
    author_type: 1,
    author_id: "user_1".to_string(),
    reply_message_id: None,
    metadata: None,
    is_sync: false,
  };

  // Insert message
  upsert_chat_messages(db_conn, &[message]).unwrap();

  // Check original content
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let original = select_message(db_conn, message_id).unwrap().unwrap();
  assert_eq!(original.content, "Original content");

  // Create updated message with same ID but different content
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let updated_message = ChatMessageTable {
    message_id, // Same ID
    chat_id: chat_id.clone(),
    content: "Updated content".to_string(), // New content
    created_at: 1625097700,                 // Updated timestamp
    author_type: 1,
    author_id: "user_1".to_string(),
    reply_message_id: Some(1000), // Added reply ID
    metadata: Some(r#"{"updated": true}"#.to_string()),
    is_sync: false,
  };

  // Upsert message
  upsert_chat_messages(db_conn, &[updated_message]).unwrap();

  // Verify update
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result = select_message(db_conn, message_id).unwrap().unwrap();
  assert_eq!(result.content, "Updated content");
  assert_eq!(result.created_at, 1625097700);
  assert_eq!(result.reply_message_id, Some(1000));
  assert_eq!(result.metadata, Some(r#"{"updated": true}"#.to_string()));

  // Count should still be 1 (update, not insert)
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let count = total_message_count(db_conn, &chat_id).unwrap();
  assert_eq!(count, 1);
}

#[tokio::test]
async fn chat_message_select_with_large_dataset() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();

  // Create 100 test messages with sequential IDs
  let mut messages = Vec::new();
  for i in 1..=100 {
    messages.push(ChatMessageTable {
      message_id: i * 100,
      chat_id: chat_id.clone(),
      content: format!("Message {}", i),
      created_at: 1625097600 + (i * 10), // Increasing timestamps
      author_type: if i % 2 == 0 { 0 } else { 1 }, // Alternate between AI and User
      author_id: if i % 2 == 0 {
        "ai".to_string()
      } else {
        "user_1".to_string()
      },
      reply_message_id: if i > 1 && i % 2 == 0 {
        Some((i - 1) * 100)
      } else {
        None
      }, // Even messages reply to previous message
      metadata: if i % 5 == 0 {
        Some(format!(r#"{{"index": {}}}"#, i))
      } else {
        None
      },
      is_sync: false,
    });
  }

  // Insert all 100 messages
  upsert_chat_messages(db_conn, &messages).unwrap();

  // Verify total count
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let count = total_message_count(db_conn, &chat_id).unwrap();
  assert_eq!(count, 100, "Should have 100 messages in the database");

  // Test 1: MessageCursor::Offset with small page size
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let page_size = 10;
  let result_offset =
    select_chat_messages(db_conn, &chat_id, page_size, MessageCursor::Offset(0)).unwrap();

  assert_eq!(
    result_offset.messages.len(),
    page_size as usize,
    "Should return exactly {page_size} messages"
  );
  assert!(
    result_offset.has_more,
    "Should have more messages available"
  );
  assert_eq!(result_offset.total_count, 100, "Total count should be 100");

  // Test 2: Pagination with offset
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_page2 = select_chat_messages(
    db_conn,
    &chat_id,
    page_size,
    MessageCursor::Offset(page_size),
  )
  .unwrap();

  assert_eq!(result_page2.messages.len(), page_size as usize);
  assert!(
    result_page2.messages[0].message_id != result_offset.messages[0].message_id,
    "Second page should have different messages than first page"
  );

  // Test 3: MessageCursor::AfterMessageId (forward pagination)
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let middle_message_id = 5000; // Message ID from the middle
  let result_after = match select_chat_messages(
    db_conn,
    &chat_id,
    page_size,
    MessageCursor::AfterMessageId(middle_message_id),
  ) {
    Ok(result) => result,
    Err(e) if e.to_string().contains("NotFound") => {
      // If message with ID 5000 doesn't exist, try with a different ID
      let db_conn = test.user_manager.db_connection(uid).unwrap();
      select_chat_messages(
        db_conn,
        &chat_id,
        page_size,
        MessageCursor::AfterMessageId(4500),
      )
      .unwrap()
    },
    Err(e) => panic!("Failed to select messages: {}", e),
  };

  assert!(
    !result_after.messages.is_empty(),
    "Should return at least one message"
  );
  assert!(
    result_after.messages.iter().all(|m| m.message_id > 4500),
    "All messages should have ID greater than the cursor"
  );

  // Test 4: MessageCursor::BeforeMessageId (backward pagination)
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_before = match select_chat_messages(
    db_conn,
    &chat_id,
    page_size,
    MessageCursor::BeforeMessageId(middle_message_id),
  ) {
    Ok(result) => result,
    Err(e) if e.to_string().contains("NotFound") => {
      // If message with ID 5000 doesn't exist, try with a different ID
      let db_conn = test.user_manager.db_connection(uid).unwrap();
      select_chat_messages(
        db_conn,
        &chat_id,
        page_size,
        MessageCursor::BeforeMessageId(6000),
      )
      .unwrap()
    },
    Err(e) => panic!("Failed to select messages: {}", e),
  };

  assert!(
    !result_before.messages.is_empty(),
    "Should return at least one message"
  );
  assert!(
    result_before.messages.iter().all(|m| m.message_id < 6000),
    "All messages should have ID less than the cursor"
  );

  // Test 5: Large page size (retrieve all)
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_all = select_chat_messages(
    db_conn,
    &chat_id,
    200, // More than we have
    MessageCursor::Offset(0),
  )
  .unwrap();

  assert_eq!(
    result_all.messages.len(),
    100,
    "Should return all 100 messages"
  );
  assert!(!result_all.has_more, "Should not have more messages");

  // Test 6: Empty result when using out of range cursor
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_out_of_range = match select_chat_messages(
    db_conn,
    &chat_id,
    page_size,
    MessageCursor::AfterMessageId(10000), // After the last message
  ) {
    Ok(result) => result,
    Err(e) if e.to_string().contains("NotFound") => {
      // Use Offset(0) with limit 0 to get an empty result with the right structure
      let db_conn = test.user_manager.db_connection(uid).unwrap();
      select_chat_messages(db_conn, &chat_id, 0, MessageCursor::Offset(0)).unwrap()
    },
    Err(e) => panic!("Failed to select messages: {}", e),
  };

  // If we get to this point, we can just verify has_more is false
  assert!(
    !result_out_of_range.has_more,
    "Should not have more messages"
  );
}

#[tokio::test]
async fn chat_message_order_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();

  // Create test messages with different timestamps but out-of-order IDs
  // to verify which field controls the sorting
  let messages = vec![
    ChatMessageTable {
      message_id: 2000, // Higher ID but earlier timestamp
      chat_id: chat_id.clone(),
      content: "Message 2".to_string(),
      created_at: 1625097600, // Earlier
      author_type: 1,
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
    ChatMessageTable {
      message_id: 1000, // Lower ID but later timestamp
      chat_id: chat_id.clone(),
      content: "Message 1".to_string(),
      created_at: 1625097700, // Later
      author_type: 1,
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
    ChatMessageTable {
      message_id: 3000,
      chat_id: chat_id.clone(),
      content: "Message 3".to_string(),
      created_at: 1625097800, // Latest
      author_type: 1,
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
  ];

  // Insert messages
  upsert_chat_messages(db_conn, &messages).unwrap();

  // Test 1: Verify default order (should be by created_at, not message_id)
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result = select_chat_messages(db_conn, &chat_id, 10, MessageCursor::Offset(0)).unwrap();

  assert_eq!(result.messages.len(), 3);

  // Check if ordered by created_at (descending)
  let is_ordered_by_created_at_desc = result
    .messages
    .windows(2)
    .all(|w| w[0].created_at >= w[1].created_at);

  assert!(
    is_ordered_by_created_at_desc,
    "Messages are not ordered by created_at in descending order"
  );

  println!(
    "Message order is {}",
    if is_ordered_by_created_at_desc {
      "descending by created_at"
    } else {
      "not descending by created_at"
    }
  );

  // Test 2: Test cursor with AfterMessageId
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let middle_message = &result.messages[1];
  let result_after = select_chat_messages(
    db_conn,
    &chat_id,
    10,
    MessageCursor::AfterMessageId(middle_message.message_id),
  )
  .unwrap();

  // With our simplified implementation, we should get messages with ID > middle_message.message_id
  for msg in &result_after.messages {
    assert!(
      msg.message_id > middle_message.message_id,
      "Message with ID {} should have higher ID than middle message ({})",
      msg.message_id,
      middle_message.message_id
    );
  }

  // Test 3: Test cursor with BeforeMessageId
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_before = select_chat_messages(
    db_conn,
    &chat_id,
    10,
    MessageCursor::BeforeMessageId(middle_message.message_id),
  )
  .unwrap();

  // With our simplified implementation, we should get messages with ID < middle_message.message_id
  for msg in &result_before.messages {
    assert!(
      msg.message_id < middle_message.message_id,
      "Message with ID {} should have lower ID than middle message ({})",
      msg.message_id,
      middle_message.message_id
    );
  }

  // Test 4: Create messages with identical timestamps but different IDs
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let same_time_messages = vec![
    ChatMessageTable {
      message_id: 4000,
      chat_id: chat_id.clone(),
      content: "Same time 1".to_string(),
      created_at: 1625098000, // Same timestamp
      author_type: 1,
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
    ChatMessageTable {
      message_id: 5000,
      chat_id: chat_id.clone(),
      content: "Same time 2".to_string(),
      created_at: 1625098000, // Same timestamp
      author_type: 1,
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    },
  ];

  upsert_chat_messages(db_conn, &same_time_messages).unwrap();

  // Fetch all messages
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let result_all = select_chat_messages(db_conn, &chat_id, 10, MessageCursor::Offset(0)).unwrap();

  assert_eq!(result_all.messages.len(), 5);

  // Find our two messages with identical timestamps
  let same_time_results: Vec<&ChatMessageTable> = result_all
    .messages
    .iter()
    .filter(|m| m.created_at == 1625098000)
    .collect();

  assert_eq!(
    same_time_results.len(),
    2,
    "Should find both messages with same timestamp"
  );

  // Verify that message_id is used as a secondary sort key when timestamps are identical
  if same_time_results[0].message_id > same_time_results[1].message_id {
    // If we're in descending order (which we are), higher IDs should come first
    assert!(
      same_time_results[0].created_at >= same_time_results[1].created_at,
      "When timestamps are equal, messages should be ordered by message_id"
    );
  } else {
    // This shouldn't happen with our current implementation
    panic!("Unexpected ordering of messages with identical timestamps");
  }
}

#[tokio::test]
async fn chat_message_cursor_order_consistency_test() {
  use_localhost_af_cloud().await;
  let test = EventIntegrationTest::new().await;
  test.sign_up_as_anon().await;

  let uid = test.user_manager.get_anon_user().await.unwrap().id;
  let db_conn = test.user_manager.db_connection(uid).unwrap();

  let chat_id = Uuid::new_v4().to_string();

  // Create 20 test messages with sequential timestamps
  let mut messages = Vec::new();
  for i in 1..=20 {
    messages.push(ChatMessageTable {
      message_id: i * 100,
      chat_id: chat_id.clone(),
      content: format!("Message {}", i),
      created_at: 1625097600 + (i * 100), // Increasing timestamps with good separation
      author_type: 1,
      author_id: "user_1".to_string(),
      reply_message_id: None,
      metadata: None,
      is_sync: false,
    });
  }

  // Insert messages
  upsert_chat_messages(db_conn, &messages).unwrap();

  // Determine the ordering (ascending or descending)
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let first_page = select_chat_messages(db_conn, &chat_id, 5, MessageCursor::Offset(0)).unwrap();
  let is_descending = first_page.messages[0].created_at > first_page.messages[1].created_at;

  println!(
    "Message order is {}",
    if is_descending {
      "descending"
    } else {
      "ascending"
    }
  );

  // Test forward pagination consistency
  // First, get page 1 with offset
  let first_with_offset = first_page;
  assert_eq!(first_with_offset.messages.len(), 5);

  // Then get page 2 with offset
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let second_with_offset =
    select_chat_messages(db_conn, &chat_id, 5, MessageCursor::Offset(5)).unwrap();
  assert!(
    !second_with_offset.messages.is_empty(),
    "Second page should have at least one message"
  );

  // Now get page 2 using AfterMessageId based on the last message of page 1
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let last_msg_of_first_page = &first_with_offset.messages[4];
  let second_with_after = select_chat_messages(
    db_conn,
    &chat_id,
    5,
    MessageCursor::AfterMessageId(last_msg_of_first_page.message_id),
  )
  .unwrap();

  // The AfterMessageId cursor should return messages with IDs > last_msg_of_first_page.message_id
  assert!(
    !second_with_after.messages.is_empty(),
    "Second page with AfterMessageId should have at least one message"
  );

  println!(
    "Offset-based page size: {}",
    second_with_offset.messages.len()
  );
  println!(
    "Cursor-based page size: {}",
    second_with_after.messages.len()
  );

  // Check that all returned messages have message_id > last_msg_of_first_page.message_id
  for msg in &second_with_after.messages {
    assert!(
      msg.message_id > last_msg_of_first_page.message_id,
      "Message ID {} should be greater than last message of first page ({})",
      msg.message_id,
      last_msg_of_first_page.message_id
    );
  }

  // Test backward pagination
  // Get the third page with offset
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let third_with_offset =
    select_chat_messages(db_conn, &chat_id, 5, MessageCursor::Offset(10)).unwrap();
  assert!(
    !third_with_offset.messages.is_empty(),
    "Third page should have at least one message"
  );

  // Now go back to the second page using BeforeMessageId based on the first message of third page
  let db_conn = test.user_manager.db_connection(uid).unwrap();
  let first_msg_of_third_page = &third_with_offset.messages[0];
  let second_with_before = select_chat_messages(
    db_conn,
    &chat_id,
    5,
    MessageCursor::BeforeMessageId(first_msg_of_third_page.message_id),
  )
  .unwrap();

  assert!(
    !second_with_before.messages.is_empty(),
    "Second page with BeforeMessageId should have at least one message"
  );
  println!(
    "Before-based page size: {}",
    second_with_before.messages.len()
  );

  // Check that all returned messages have message_id < first_msg_of_third_page.message_id
  for msg in &second_with_before.messages {
    assert!(
      msg.message_id < first_msg_of_third_page.message_id,
      "Message ID {} should be less than first message of third page ({})",
      msg.message_id,
      first_msg_of_third_page.message_id
    );
  }
}
