#ifndef DEVICE_CTRL_YTJ_VIDICON_H
#define DEVICE_CTRL_YTJ_VIDICON_H
#include <QObject>

#include "common/snowflake/snowflake.h"
#include "common/utils/base64_util.h"
#include "common/utils/biz_lock.h"
#include "common/utils/date_util.h"
#include "common/utils/json_util.h"
#include "mqtt/mqtt_cli.h"

namespace zsy
{
    struct SnapshotRequestPayload
    {
        std::string type{"snapshot"};
    };

    struct SnapshotRequestMsg
    {
        std::string id{Snowflake::genIdStr()};
        std::string sn;
        std::string name{"snapshot"};
        std::string version{"1.0"};
        uint64_t timestamp{DateUtil::timestamp<std::chrono::seconds>()};
        SnapshotRequestPayload payload;
    };

    inline void to_json(nlohmann::json &j, const SnapshotRequestPayload &o)
    {
        j = nlohmann::json{
            {"type", o.type},
            {"body", nlohmann::json::object()}
        };
    }

    inline void to_json(nlohmann::json &j, const SnapshotRequestMsg &o)
    {
        j = nlohmann::json{
            {"id", o.id},
            {"sn", o.sn},
            {"name", o.name},
            {"version", o.version},
            {"timestamp", o.timestamp},
            {"payload", o.payload}
        };
    }

    struct SnapshotResultPayload
    {
        int32_t state_code;
        std::string imageformat;
        std::string imgPath;
        std::string image_content;
    };

    struct SnapshotResultMsg
    {
        std::string id;
        int32_t bv;
        std::string sn;
        std::string name;
        std::string version;
        int64_t timestamp;
        SnapshotResultPayload payload;
    };


    inline void from_json(const nlohmann::json &j, SnapshotResultPayload &o)
    {
        JSON_FIELD(state_code);
        JSON_FIELD(imageformat);
        JSON_FIELD(imgPath);
        JSON_FIELD(image_content);
    }

    inline void from_json(const nlohmann::json &j, SnapshotResultMsg &o)
    {
        JSON_FIELD(id);
        JSON_FIELD(bv);
        JSON_FIELD(sn);
        JSON_FIELD(name);
        JSON_FIELD(version);
        JSON_FIELD(timestamp);
        JSON_FIELD(payload);
    }

    struct SnapshotReplyMsg
    {
        std::string id;
        std::string sn;
        std::string name;
        int32_t code;
        std::string version;
        int64_t timestamp;
    };

    inline void from_json(const nlohmann::json &j, SnapshotReplyMsg &o)
    {
        JSON_FIELD(id);
        JSON_FIELD(sn);
        JSON_FIELD(name);
        JSON_FIELD(code);
        JSON_FIELD(version);
        JSON_FIELD(timestamp);
    }

    struct Plate
    {
        std::string imageFile;
        std::string license;
    };

    struct Result
    {
        Plate plateResult;
    };

    struct AlarmInfo
    {
        std::string deviceName;
        std::string ipaddr;
        Result result;
        std::string serialno;
    };

    struct RecognizeResult
    {
        AlarmInfo alarmInfoPlate;
    };

    struct RecognizeResultWrapper
    {
        std::string id;
        RecognizeResult payload;
    };

    inline void from_json(const nlohmann::json &j, Plate &o)
    {
        JSON_FIELD_SPARE(imageFile, full_image_content);
        JSON_FIELD(license);
        if (!o.license.empty())
        {
            o.license = Base64::decode(o.license);
        }
    }

    inline void from_json(const nlohmann::json &j, Result &o)
    {
        JSON_FIELD_SPARE(plateResult, PlateResult);
    }

    inline void from_json(const nlohmann::json &j, AlarmInfo &o)
    {
        JSON_FIELD(result);
        JSON_FIELD(serialno);
    }

    inline void from_json(const nlohmann::json &j, RecognizeResult &o)
    {
        JSON_FIELD_SPARE(alarmInfoPlate, AlarmInfoPlate);
    }

    inline void from_json(const nlohmann::json &j, RecognizeResultWrapper &o)
    {
        JSON_FIELD(id);
        JSON_FIELD(payload);
    }


    class YtjVidicon : public QObject
    {
        Q_OBJECT
        std::shared_ptr<MQTTCli> mqttCli;
        std::shared_ptr<BizLock> bizLock;

        std::string devSn;
        uint32_t timeout;


        enum class SnapshotStatus
        {
            Pending,
            Success,
            Failed,
            Canceled,
        };

        struct PhotoInfo
        {
            SnapshotStatus status{SnapshotStatus::Pending};
            uint64_t timestamp = DateUtil::timestamp<std::chrono::seconds>();
            std::string imageformat;
            std::string image_content;
        };

        PhotoInfo photoInfo;
        std::mutex photoInfo_mtx;
        std::condition_variable_any photoInfoChangeCV;

        void snapshot(const MQTTMsg &msg);

        void snapshotReply(const MQTTMsg &msg);

        void updatePhotoInfo(SnapshotStatus status, const std::string &content, const std::string &format);

    public:
        YtjVidicon(std::string devSn, uint32_t timeout, uint32_t enableRecognize, std::shared_ptr<MQTTCli> mqttCli);

        std::string photograph();

        /**
         * @brief 解析识别结果
         * @param jsonStr 识别结果 JSON 字符串
         * @return 包含识别结果的元组，否成功、识别标识、车牌号、图像内容
         */
        std::tuple<bool, std::string, std::string, std::string> parseRecognizeResult(const std::string &jsonStr);

        Q_SIGNALS:
        

        void recognizeComplete(bool success, std::string id, std::string licensePlate, std::string image);
    };
} // zsy

#endif //DEVICE_CTRL_YTJ_VIDICON_H