package com.tiedup.remake.v2.furniture;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class FurnitureSeatSyncCodecTest {

    private static final UUID U1 = UUID.fromString(
        "00000000-0000-0000-0000-000000000001"
    );
    private static final UUID U2 = UUID.fromString(
        "00000000-0000-0000-0000-000000000002"
    );

    @Test
    @DisplayName("empty map encodes to empty string")
    void empty() {
        assertEquals("", FurnitureSeatSyncCodec.encode(Map.of()));
        assertTrue(FurnitureSeatSyncCodec.decode("").isEmpty());
    }

    @Test
    @DisplayName("single entry round-trip")
    void single() {
        Map<UUID, String> m = new LinkedHashMap<>();
        m.put(U1, "left");
        String wire = FurnitureSeatSyncCodec.encode(m);
        assertEquals(U1 + ";left", wire);
        assertEquals(m, FurnitureSeatSyncCodec.decode(wire));
    }

    @Test
    @DisplayName("multi entry round-trip preserves insertion order")
    void multi() {
        Map<UUID, String> m = new LinkedHashMap<>();
        m.put(U1, "left");
        m.put(U2, "right");
        String wire = FurnitureSeatSyncCodec.encode(m);
        Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
        assertEquals(m, back);
    }

    @Test
    @DisplayName("decode skips corrupt UUIDs and preserves valid entries")
    void skipsCorrupt() {
        String wire = "not-a-uuid;left|" + U2 + ";right";
        Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
        assertEquals(1, back.size());
        assertEquals("right", back.get(U2));
    }

    @Test
    @DisplayName("decode rejects entries with missing seat id")
    void rejectsEmptySeatId() {
        String wire = U1 + ";";
        assertTrue(FurnitureSeatSyncCodec.decode(wire).isEmpty());
    }

    @Test
    @DisplayName("decode tolerates null input")
    void nullInput() {
        assertTrue(FurnitureSeatSyncCodec.decode(null).isEmpty());
    }

    @Test
    @DisplayName("decode skips entries with no separator")
    void skipsNoSeparator() {
        String wire = "abc|" + U1 + ";right";
        Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
        assertEquals(1, back.size());
        assertEquals("right", back.get(U1));
    }

    @Test
    @DisplayName("decode skips entries starting with separator")
    void skipsLeadingSeparator() {
        String wire = ";seat|" + U1 + ";right";
        Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
        assertEquals(1, back.size());
        assertEquals("right", back.get(U1));
    }
}
