#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/db/include/txn_id.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/eye/verification_source.h>

#include <maps/libs/enum_io/include/enum_io_fwd.h>
#include <maps/libs/sql_chemistry/include/gateway_access.h>

#include <maps/libs/json/include/value.h>

#include <optional>
#include <string>
#include <utility>
#include <vector>

namespace maps::mrc::db::eye {

enum class VerifiedDetectionMissingOnFrameIsVisible {
    Yes,
    No,
    Unknown,
};

DECLARE_ENUM_IO(VerifiedDetectionMissingOnFrameIsVisible);

enum class VerifiedDetectionMissingOnFrameMissingReason {
    Missing,
    Hidden,
    PlaceIsNotVisible,
    Unknown,
};

DECLARE_ENUM_IO(VerifiedDetectionMissingOnFrameMissingReason);


class VerifiedDetectionMissingOnFrame {
public:
    VerifiedDetectionMissingOnFrame(
            VerificationSource source,
            TId detectionId,
            TId frameId,
            std::optional<VerifiedDetectionMissingOnFrameIsVisible> isVisible = std::nullopt,
            std::optional<VerifiedDetectionMissingOnFrameMissingReason> missingReason = std::nullopt);

    TId id() const { return id_; }

    VerificationSource source() const { return source_; }

    TId txnId() const { return txnId_; }

    TId detectionId() const { return detectionId_; }

    TId frameId() const { return frameId_; }

    std::optional<VerifiedDetectionMissingOnFrameIsVisible> isVisible() const {
        return isVisible_;
    }

    VerifiedDetectionMissingOnFrame& setIsVisible(VerifiedDetectionMissingOnFrameIsVisible isVisible) {
        isVisible_ = isVisible;
        return *this;
    }

    std::optional<VerifiedDetectionMissingOnFrameMissingReason> missingReason() const {
        return missingReason_;
    }

    VerifiedDetectionMissingOnFrame& setMissingReason(VerifiedDetectionMissingOnFrameMissingReason missingReason) {
        missingReason_ = missingReason;
        return *this;
    }

private:
    friend class sql_chemistry::GatewayAccess<VerifiedDetectionMissingOnFrame>;
    friend class TxnIdAccess<VerifiedDetectionMissingOnFrame>;

    VerifiedDetectionMissingOnFrame() {};

    VerifiedDetectionMissingOnFrame& setTxnId(TId txnId) {
        txnId_ = txnId;
        return *this;
    }

    template <typename T>
    static auto introspect(T& t)
    {
        return std::tie(t.id_, t.source_, t.txnId_, t.detectionId_, t.frameId_, t.isVisible_, t.missingReason_);
    }

    TId id_;
    VerificationSource source_;
    TId txnId_;
    TId detectionId_;
    TId frameId_;
    std::optional<VerifiedDetectionMissingOnFrameIsVisible> isVisible_;
    std::optional<VerifiedDetectionMissingOnFrameMissingReason> missingReason_;

public:
    auto introspect() const { return introspect(*this); }
};

class VerifiedDetectionMissingOnFrameToTolokaTask {
public:
    VerifiedDetectionMissingOnFrameToTolokaTask(
            TId verifiedTaskId,
            TId tolokaTaskId);

    TId verifiedTaskId() const { return verifiedTaskId_; }

    TId tolokaTaskId() const { return tolokaTaskId_; }

private:
    friend class sql_chemistry::GatewayAccess<VerifiedDetectionMissingOnFrameToTolokaTask>;

    VerifiedDetectionMissingOnFrameToTolokaTask() {};

    template <typename T>
    static auto introspect(T& t)
    {
        return std::tie(t.verifiedTaskId_, t.tolokaTaskId_);
    }

    TId verifiedTaskId_;
    TId tolokaTaskId_;

public:
    auto introspect() const { return introspect(*this); }
};


using VerifiedDetectionMissingOnFrames = std::vector<VerifiedDetectionMissingOnFrame>;
using VerifiedDetectionMissingOnFramesToTolokaTasks = std::vector<VerifiedDetectionMissingOnFrameToTolokaTask>;

} // namespace maps::mrc::db::eye
