#pragma once

#include "common.h"

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

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

namespace maps::mrc::db {

class TakeoutDataErasure {
public:
    TakeoutDataErasure(std::string takeoutRequestId,
                       std::string userId,
                       chrono::TimePoint requestedAt)
        : takeoutRequestId_(std::move(takeoutRequestId))
        , userId_(std::move(userId))
        , requestedAt_(requestedAt)
    {
    }

    TId id() const { return id_; }

    const std::string& takeoutRequestId() const { return takeoutRequestId_; }

    const std::string& userId() const { return userId_; }

    chrono::TimePoint requestedAt() const { return requestedAt_; }

    std::optional<chrono::TimePoint> finishedAt() const { return finishedAt_; }

    TakeoutDataErasure& setTakeoutRequestId(std::string takeoutRequestId)
    {
        takeoutRequestId_ = std::move(takeoutRequestId);
        return *this;
    }

    TakeoutDataErasure& setUserId(std::string userId)
    {
        userId_ = std::move(userId);
        return *this;
    }

    TakeoutDataErasure& setRequestedAt(chrono::TimePoint requestedAt)
    {
        requestedAt_ = requestedAt;
        return *this;
    }

    TakeoutDataErasure& setFinishedAt(chrono::TimePoint finishedAt)
    {
        finishedAt_ = finishedAt;
        return *this;
    }

    TakeoutDataErasure& resetFinishedAt()
    {
        finishedAt_ = std::nullopt;
        return *this;
    }

    TakeoutDataErasure& setGrinderTaskId(std::string grinderTaskId)
    {
        grinderTaskId_ = std::move(grinderTaskId);
        return *this;
    }

    TakeoutDataErasure& resetGrinderTaskId()
    {
        grinderTaskId_ = std::nullopt;
        return *this;
    }

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

    TakeoutDataErasure() = default;

    template <typename T>
    static auto introspect(T& t)
    {
        return std::tie(t.id_,
                        t.takeoutRequestId_,
                        t.userId_,
                        t.requestedAt_,
                        t.finishedAt_,
                        t.grinderTaskId_);
    }

    TId id_{};
    std::string takeoutRequestId_{};
    std::string userId_{};
    chrono::TimePoint requestedAt_{};
    std::optional<chrono::TimePoint> finishedAt_{};
    std::optional<std::string> grinderTaskId_{};

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

using TakeoutDataErasures = std::vector<TakeoutDataErasure>;

}  // namespace maps::mrc::db
