package com.lingniu.ingest.protocol.gb32960.inbound;

import com.lingniu.ingest.protocol.gb32960.model.CommandType;
import org.junit.jupiter.api.Test;

import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;

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

class Gb32960ConnectionDiagnosticsTest {

    private static final Instant NOW = Instant.parse("2026-06-29T10:00:00Z");

    @Test
    void tracksActiveSessionCommandPlatformAccountAndReadIdleCount() {
        MutableClock clock = new MutableClock(NOW);
        Gb32960ConnectionDiagnostics diagnostics = new Gb32960ConnectionDiagnostics(clock);

        diagnostics.opened("session-1", "127.0.0.1:65469");
        clock.advanceSeconds(5);
        diagnostics.received("session-1", CommandType.PLATFORM_LOGIN, "");
        diagnostics.platformLoginAccepted("session-1", "Hyundai");
        clock.advanceSeconds(30);
        diagnostics.readIdle("session-1");

        assertThat(diagnostics.activeSessions()).singleElement().satisfies(session -> {
            assertThat(session.sessionId()).isEqualTo("session-1");
            assertThat(session.peer()).isEqualTo("127.0.0.1:65469");
            assertThat(session.connectedAt()).isEqualTo(NOW);
            assertThat(session.lastInboundAt()).isEqualTo(NOW.plusSeconds(5));
            assertThat(session.idleSeconds()).isEqualTo(30);
            assertThat(session.lastCommandCode()).isEqualTo(0x05);
            assertThat(session.lastCommand()).isEqualTo("PLATFORM_LOGIN");
            assertThat(session.vin()).isEmpty();
            assertThat(session.platformAccount()).isEqualTo("Hyundai");
            assertThat(session.readIdleCount()).isEqualTo(1);
        });
    }

    @Test
    void removesSessionWhenChannelCloses() {
        Gb32960ConnectionDiagnostics diagnostics = new Gb32960ConnectionDiagnostics(Clock.fixed(NOW, ZoneOffset.UTC));

        diagnostics.opened("session-1", "127.0.0.1:65469");
        diagnostics.closed("session-1");

        assertThat(diagnostics.activeSessions()).isEmpty();
    }

    private static final class MutableClock extends Clock {
        private Instant instant;

        private MutableClock(Instant instant) {
            this.instant = instant;
        }

        void advanceSeconds(long seconds) {
            instant = instant.plusSeconds(seconds);
        }

        @Override
        public ZoneOffset getZone() {
            return ZoneOffset.UTC;
        }

        @Override
        public Clock withZone(java.time.ZoneId zone) {
            return this;
        }

        @Override
        public Instant instant() {
            return instant;
        }
    }
}
