package com.lingniu.ingest.tdenginehistory;

import org.junit.jupiter.api.Test;

import java.time.Instant;

import static org.assertj.core.api.Assertions.assertThat;

class TdengineHistoryQueriesTest {

    private final TdengineHistorySchema schema = new TdengineHistorySchema("vehicle_history");
    private final TdengineHistoryQueries queries = new TdengineHistoryQueries(schema);

    @Test
    void rawFrameQueryUsesVehicleChildTableAndKeysetPagination() {
        TdengineRawFrameQuery query = new TdengineRawFrameQuery(
                "JT808",
                "jt808:g7gps",
                Instant.parse("2026-06-29T00:00:00Z"),
                Instant.parse("2026-06-30T00:00:00Z"),
                TdengineQueryOrder.ASC,
                101,
                new TdenginePageCursor(Instant.parse("2026-06-29T01:00:00Z"), "frame-100"));

        TdengineQueryStatement statement = queries.rawFrames(query);

        assertThat(statement.sql())
                .startsWith("SELECT ts, frame_id, received_at, message_id")
                .contains(" FROM raw_jt808_")
                .contains(" WHERE ts >= ? AND ts < ?")
                .contains(" AND (ts > ? OR (ts = ? AND frame_id > ?))")
                .contains(" ORDER BY ts ASC, frame_id ASC LIMIT ?");
        assertThat(statement.values())
                .containsExactly(
                        query.from(), query.to(),
                        query.cursor().ts(), query.cursor().ts(), query.cursor().tieBreaker(),
                        101);
    }

    @Test
    void rawFrameQueryUsesStableWhenPhoneMessageIdOrParseStatusFiltersArePresent() {
        TdengineRawFrameQuery query = new TdengineRawFrameQuery(
                "JT808",
                "",
                "",
                "13079963320",
                0x0100,
                "SUCCEEDED",
                Instant.parse("2026-06-29T00:00:00Z"),
                Instant.parse("2026-06-30T00:00:00Z"),
                TdengineQueryOrder.DESC,
                50,
                new TdenginePageCursor(Instant.parse("2026-06-29T12:00:00Z"), "frame-100"));

        TdengineQueryStatement statement = queries.rawFrames(query);

        assertThat(statement.sql())
                .startsWith("SELECT ts, frame_id, received_at, message_id")
                .contains(" FROM raw_frames")
                .contains(" WHERE ts >= ? AND ts < ?")
                .contains(" AND protocol = ?")
                .contains(" AND phone = ?")
                .contains(" AND message_id = ?")
                .contains(" AND parse_status = ?")
                .contains(" AND (ts < ? OR (ts = ? AND frame_id < ?))")
                .contains(" ORDER BY ts DESC, frame_id DESC LIMIT ?");
        assertThat(statement.values())
                .containsExactly(
                        query.from(), query.to(),
                        "JT808", "13079963320", 0x0100, "SUCCEEDED",
                        query.cursor().ts(), query.cursor().ts(), query.cursor().tieBreaker(),
                        50);
    }

    @Test
    void locationQueryCapsLimitAndUsesDescendingCursor() {
        TdengineLocationQuery query = new TdengineLocationQuery(
                "GB32960",
                "vin:VIN123",
                Instant.parse("2026-06-29T00:00:00Z"),
                Instant.parse("2026-06-30T00:00:00Z"),
                TdengineQueryOrder.DESC,
                5000,
                new TdenginePageCursor(Instant.parse("2026-06-29T20:00:00Z"), "fact-200"));

        TdengineQueryStatement statement = queries.locations(query);

        assertThat(statement.sql())
                .contains(" FROM loc_gb32960_")
                .contains(" AND (ts < ? OR (ts = ? AND fact_id < ?))")
                .contains(" ORDER BY ts DESC, fact_id DESC LIMIT ?");
        assertThat(statement.values().getLast()).isEqualTo(1001);
    }

}
