package com.dexorder.flink.publisher;

import com.dexorder.proto.Tick;
import org.apache.flink.api.common.serialization.DeserializationSchema;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * Kafka deserializer for Tick protobuf messages from the market-tick topic.
 *
 * Wire format: [0x01 version][0x03 TICK type][Tick protobuf bytes]
 */
public class TickDeserializer implements DeserializationSchema<TickWrapper> {
    private static final Logger LOG = LoggerFactory.getLogger(TickDeserializer.class);
    private static final long serialVersionUID = 1L;

    private static final byte PROTOCOL_VERSION = 0x01;
    private static final byte MSG_TYPE_TICK = 0x03;

    @Override
    public TickWrapper deserialize(byte[] message) throws IOException {
        try {
            if (message.length < 2) {
                throw new IOException("Message too short: " + message.length + " bytes");
            }

            if (message[0] != PROTOCOL_VERSION) {
                throw new IOException("Unsupported protocol version: 0x" + Integer.toHexString(message[0] & 0xFF));
            }

            if (message[1] != MSG_TYPE_TICK) {
                throw new IOException("Unexpected message type: 0x" + Integer.toHexString(message[1] & 0xFF));
            }

            byte[] payload = new byte[message.length - 2];
            System.arraycopy(message, 2, payload, 0, payload.length);

            Tick tick = Tick.parseFrom(payload);

            return new TickWrapper(
                    tick.getTicker(),
                    tick.getTradeId(),
                    tick.getTimestamp(),
                    tick.getPrice(),
                    tick.getAmount(),
                    tick.getQuoteAmount(),
                    tick.getTakerBuy()
            );

        } catch (Exception e) {
            LOG.warn("Failed to deserialize Tick, skipping: {}", e.getMessage());
            // Return null; Flink's KafkaSource skips nulls via filter
            return null;
        }
    }

    @Override
    public boolean isEndOfStream(TickWrapper nextElement) {
        return false;
    }

    @Override
    public TypeInformation<TickWrapper> getProducedType() {
        return TypeInformation.of(TickWrapper.class);
    }
}
