package at.procon.eventhub.yellowfox.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class YellowFoxD8BookingRowMapperTest {

    @Test
    void trimsVehicleRegistrationValuesInReferencesAndPayload() throws SQLException {
        YellowFoxD8BookingRowMapper mapper = new YellowFoxD8BookingRowMapper(new ObjectMapper());
        ResultSet rs = mock(ResultSet.class);
        OffsetDateTime occurredAt = OffsetDateTime.parse("2026-05-08T10:15:30+02:00");

        when(rs.getString("eventid")).thenReturn("  evt-1  ");
        when(rs.getObject("utc", OffsetDateTime.class)).thenReturn(occurredAt);
        when(rs.getInt("vehicle_id")).thenReturn(42);
        when(rs.getInt("driver_id")).thenReturn(7);
        when(rs.getInt("fleet_id")).thenReturn(9);
        when(rs.getInt("odometer")).thenReturn(1234);
        when(rs.getInt("telematic_provider_id")).thenReturn(3);
        when(rs.getInt("ignition")).thenReturn(1);
        when(rs.getInt("previous_ignition")).thenReturn(0);
        when(rs.getInt("eventtype")).thenReturn(2);
        when(rs.getInt("state")).thenReturn(3);
        when(rs.wasNull()).thenReturn(false);
        when(rs.getString("vehicle_vrn")).thenReturn("  W-12345  ");
        when(rs.getString("vehicle_vin")).thenReturn("  vin-123  ");
        when(rs.getString("driver_card_number")).thenReturn("  card-9  ");
        when(rs.getString("fleet_name")).thenReturn("  Fleet 9  ");
        when(rs.getString("driver_firstname")).thenReturn("  Ada  ");
        when(rs.getString("driver_lastname")).thenReturn("  Lovelace  ");
        when(rs.getString("telematic_provider_name")).thenReturn("  YellowFox  ");
        when(rs.getString("key")).thenReturn("  booking-key  ");
        when(rs.getString("payload")).thenReturn("""
                {"vrn":"  W-12345  ","nested":{"label":"  value  "},"list":["  x  ",1]}
                """);

        var booking = mapper.map(rs, "tenant-1", "instance-1", "setting-1");

        assertThat(booking.eventId()).isEqualTo("evt-1");
        assertThat(booking.key()).isEqualTo("booking-key");
        assertThat(booking.previousIgnition()).isEqualTo(0);
        assertThat(booking.vehicleRef().vin()).isEqualTo("VIN-123");
        assertThat(booking.vehicleRef().vehicleRegistration().number()).isEqualTo("W-12345");
        assertThat(booking.payload()).containsEntry("vrn", "W-12345");
        assertThat(booking.payload()).containsEntry("vehicleVrn", "W-12345");
        assertThat(booking.payload()).containsEntry("driverFirstName", "Ada");
        assertThat(booking.payload()).containsEntry("telematicProviderName", "YellowFox");
        assertThat(((Map<?, ?>) booking.payload().get("nested")).get("label")).isEqualTo("value");
        assertThat((List<Object>) booking.payload().get("list")).containsExactly("x", 1);
    }

    @Test
    void truncatesBookingDriverCardNumberToFirst14Characters() throws SQLException {
        YellowFoxD8BookingRowMapper mapper = new YellowFoxD8BookingRowMapper(new ObjectMapper());
        ResultSet rs = mock(ResultSet.class);
        OffsetDateTime occurredAt = OffsetDateTime.parse("2026-05-08T10:15:30+02:00");

        when(rs.getString("eventid")).thenReturn("evt-2");
        when(rs.getObject("utc", OffsetDateTime.class)).thenReturn(occurredAt);
        when(rs.getInt("vehicle_id")).thenReturn(0);
        when(rs.getInt("driver_id")).thenReturn(0);
        when(rs.getInt("fleet_id")).thenReturn(0);
        when(rs.getInt("odometer")).thenReturn(0);
        when(rs.getInt("telematic_provider_id")).thenReturn(0);
        when(rs.getInt("ignition")).thenReturn(1);
        when(rs.getInt("previous_ignition")).thenReturn(0);
        when(rs.getInt("eventtype")).thenReturn(2);
        when(rs.getInt("state")).thenReturn(3);
        when(rs.wasNull()).thenReturn(true);
        when(rs.getString("driver_card_number")).thenReturn(" 12345678901234AB ");
        when(rs.getString("payload")).thenReturn("{}");

        var booking = mapper.map(rs, "tenant-1", "instance-1", "setting-1");

        assertThat(booking.driverRef()).isNotNull();
        assertThat(booking.driverRef().driverCard()).isNotNull();
        assertThat(booking.driverRef().driverCard().number()).isEqualTo("12345678901234");
        assertThat(booking.payload()).containsEntry("driverCardNumber", "12345678901234");
    }
}
