package com.dexorder.flink.publisher;

import com.dexorder.proto.Market;
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;
import java.util.ArrayList;
import java.util.List;

/**
 * Deserializes Market protobuf messages from Kafka.
 * Expects ZMQ protocol envelope: [version byte][type_id byte][protobuf payload]
 */
public class MarketDeserializer implements DeserializationSchema<MarketWrapper> {
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = LoggerFactory.getLogger(MarketDeserializer.class);

    private static final byte PROTOCOL_VERSION = 0x01;
    private static final byte MARKET_TYPE_ID = 0x05;

    @Override
    public MarketWrapper deserialize(byte[] message) throws IOException {
        if (message == null || message.length < 3) {
            LOG.warn("Invalid message: too short (length={})", message == null ? 0 : message.length);
            return null;
        }

        // Parse ZMQ protocol envelope
        byte version = message[0];
        byte typeId = message[1];

        if (version != PROTOCOL_VERSION) {
            LOG.warn("Unknown protocol version: 0x{}", Integer.toHexString(version & 0xFF));
            return null;
        }

        if (typeId != MARKET_TYPE_ID) {
            LOG.warn("Expected MARKET type (0x05), got: 0x{}", Integer.toHexString(typeId & 0xFF));
            return null;
        }

        // Extract protobuf payload (everything after first 2 bytes)
        byte[] payload = new byte[message.length - 2];
        System.arraycopy(message, 2, payload, 0, payload.length);

        try {
            // Deserialize protobuf
            Market market = Market.parseFrom(payload);

            // Debug log the deserialized market
            LOG.info("Deserialized Market: exchange_id='{}', market_id='{}', base='{}', quote='{}'",
                    market.getExchangeId(), market.getMarketId(), market.getBaseAsset(), market.getQuoteAsset());

            // Convert to MarketWrapper
            MarketWrapper wrapper = new MarketWrapper();
            wrapper.setExchangeId(market.getExchangeId());
            wrapper.setMarketId(market.getMarketId());
            wrapper.setMarketType(market.getMarketType());
            wrapper.setDescription(market.getDescription());
            wrapper.setBaseAsset(market.getBaseAsset());
            wrapper.setQuoteAsset(market.getQuoteAsset());

            // Convert repeated field to List
            List<Integer> supportedPeriods = new ArrayList<>(market.getSupportedPeriodSecondsList());
            wrapper.setSupportedPeriodSeconds(supportedPeriods);

            wrapper.setEarliestTime(market.getEarliestTime());

            // Nautilus Instrument fields
            wrapper.setPricePrecision(market.getPricePrecision());
            wrapper.setSizePrecision(market.getSizePrecision());
            wrapper.setTickSize(market.getTickSize());
            wrapper.setLotSize(market.getLotSize());
            wrapper.setMinNotional(market.getMinNotional());
            wrapper.setMarginInit(market.getMarginInit());
            wrapper.setMarginMaint(market.getMarginMaint());
            wrapper.setMakerFee(market.getMakerFee());
            wrapper.setTakerFee(market.getTakerFee());
            wrapper.setContractMultiplier(market.getContractMultiplier());

            return wrapper;
        } catch (Exception e) {
            LOG.error("Failed to deserialize Market protobuf", e);
            return null;
        }
    }

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

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