namespace NATS.Server.Mqtt;

/// <summary>
/// MQTT protocol and server integration constants aligned with Go mqtt.go.
/// </summary>
public static class MqttProtocolConstants
{
    // MQTT fixed-header flags for SUBSCRIBE packets (MQTT 3.1.1 section 3.8.1).
    public const byte SubscribeFlags = 0x02;

    // MQTT 3.1.1 CONNACK return codes.
    public const byte ConnAckAccepted = 0x00;
    public const byte ConnAckUnacceptableProtocolVersion = 0x01;
    public const byte ConnAckIdentifierRejected = 0x02;
    public const byte ConnAckServerUnavailable = 0x03;
    public const byte ConnAckBadUserNameOrPassword = 0x04;
    public const byte ConnAckNotAuthorized = 0x05;

    // MQTT Remaining Length upper bound (max packet payload envelope).
    public const int MaxPayloadSize = 268_435_455;

    // Go mqttDefaultAckWait: 30 seconds.
    public static readonly TimeSpan DefaultAckWait = TimeSpan.FromSeconds(30);

    // Go mqttMaxAckTotalLimit.
    public const int MaxAckTotalLimit = 0xFFFF;

    // MQTT wildcard helper suffix attached to sid for synthetic "level-up" subscriptions.
    public const string MultiLevelSidSuffix = " fwc";

    // Internal MQTT subject prefixes.
    public const string Prefix = "$MQTT.";
    public const string SubPrefix = Prefix + "sub.";

    // Per-account stream names and subject prefixes.
    public const string StreamName = "$MQTT_msgs";
    public const string StreamSubjectPrefix = Prefix + "msgs.";
    public const string RetainedMsgsStreamName = "$MQTT_rmsgs";
    public const string RetainedMsgsStreamSubject = Prefix + "rmsgs.";
    public const string SessStreamName = "$MQTT_sess";
    public const string SessStreamSubjectPrefix = Prefix + "sess.";
    public const string SessionsStreamNamePrefix = "$MQTT_sess_";
    public const string QoS2IncomingMsgsStreamName = "$MQTT_qos2in";
    public const string QoS2IncomingMsgsStreamSubjectPrefix = Prefix + "qos2.in.";

    // Outbound/PUBREL stream and subject identifiers.
    public const string OutStreamName = "$MQTT_out";
    public const string OutSubjectPrefix = Prefix + "out.";
    public const string PubRelSubjectPrefix = Prefix + "out.pubrel.";
    public const string PubRelDeliverySubjectPrefix = Prefix + "deliver.pubrel.";
    public const string PubRelConsumerDurablePrefix = "$MQTT_PUBREL_";

    // JS API reply subject prefix and token positions.
    public const string JSARepliesPrefix = Prefix + "JSA.";
    public const int JSAIdTokenPos = 3;
    public const int JSATokenPos = 4;
    public const int JSAClientIDPos = 5;

    // JS API token discriminators.
    public const string JSAStreamCreate = "SC";
    public const string JSAStreamUpdate = "SU";
    public const string JSAStreamLookup = "SL";
    public const string JSAStreamDel = "SD";
    public const string JSAConsumerCreate = "CC";
    public const string JSAConsumerLookup = "CL";
    public const string JSAConsumerDel = "CD";
    public const string JSAMsgStore = "MS";
    public const string JSAMsgLoad = "ML";
    public const string JSAMsgDelete = "MD";
    public const string JSASessPersist = "SP";
    public const string JSARetainedMsgDel = "RD";
    public const string JSAStreamNames = "SN";

    // Sparkplug B constants.
    public const string SparkbNBirth = "NBIRTH";
    public const string SparkbDBirth = "DBIRTH";
    public const string SparkbNDeath = "NDEATH";
    public const string SparkbDDeath = "DDEATH";
    public static readonly byte[] SparkbNamespaceTopicPrefix = "spBv1.0/"u8.ToArray();
    public static readonly byte[] SparkbCertificatesTopicPrefix = "$sparkplug/certificates/"u8.ToArray();

    // NATS headers used when re-encoding MQTT messages.
    public const string NatsHeaderPublish = "Nmqtt-Pub";
    public const string NatsRetainedMessageTopic = "Nmqtt-RTopic";
    public const string NatsRetainedMessageOrigin = "Nmqtt-ROrigin";
    public const string NatsRetainedMessageFlags = "Nmqtt-RFlags";
    public const string NatsRetainedMessageSource = "Nmqtt-RSource";
    public const string NatsPubRelHeader = "Nmqtt-PubRel";
    public const string NatsHeaderSubject = "Nmqtt-Subject";
    public const string NatsHeaderMapped = "Nmqtt-Mapped";
}
