#pragma once

#include "common.h"
#include "enums.h"

#include <maps/libs/chrono/include/time_point.h>
#include <maps/libs/sql_chemistry/include/gateway_access.h>

#include <optional>

namespace maps::fw_updater::db {

class FirmwareUpload {
public:
    FirmwareUpload(std::string createdBy, std::string hardwareId, Slot slot, std::string version)
        : hardwareId_(std::move(hardwareId))
        , slot_(slot)
        , version_(std::move(version))
        , createdAt_(chrono::TimePoint::clock::now())
        , createdBy_(std::move(createdBy))
    {}

    TId id() const { return id_; }

    const std::string& hardwareId() const { return hardwareId_; }

    Slot slot() const { return slot_; }

    const std::string& version() const { return version_; }

    chrono::TimePoint createdAt() const { return createdAt_; }

    const std::string& createdBy() const { return createdBy_; }

    const std::string& s3UploadId() const { return s3UploadId_; }

    const std::string& s3Key() const { return s3Key_; }

    FirmwareUpload& setS3UploadId(std::string s3UploadId)
    {
        s3UploadId_ = std::move(s3UploadId);
        return *this;
    }

    FirmwareUpload& setS3Key(std::string s3Key)
    {
        s3Key_ = std::move(s3Key);
        return *this;
    }

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

    FirmwareUpload() = default;

    template <typename T>
    static auto introspect(T& t)
    {
        return std::tie(t.id_, t.hardwareId_, t.slot_, t.version_,
                        t.createdAt_, t.createdBy_, t.s3UploadId_, t.s3Key_);
    }

    TId id_{0};
    std::string hardwareId_;
    Slot slot_;
    std::string version_;
    chrono::TimePoint createdAt_;
    std::string createdBy_;
    std::string s3UploadId_;
    std::string s3Key_;

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

using FirmwareUploads = std::vector<FirmwareUpload>;

} // namespace maps::fw_updater::db
