#pragma once

#include <yandex/maps/wiki/social/common.h>
#include <yandex/maps/wiki/social/feedback/gateway_rw.h>
#include <yandex/maps/wiki/social/feedback/task.h>

#include <pqxx/pqxx>
#include <optional>

namespace maps::wiki::social::feedback {

class Agent
{
public:
    Agent(pqxx::transaction_base& socialTxn, TUid uid);

    TUid uid() const { return uid_; }
    GatewayRO& gatewayRo() { return gatewayRw_; }
    TaskForUpdate addTask(const TaskNew& newTask);
    std::optional<TaskForUpdate> taskForUpdateById(TId id);

    std::optional<TaskForUpdate> revealTaskByIdCascade(TId id);
    std::optional<TaskForUpdate> acquireTask(const TaskForUpdate& task);
    std::optional<TaskForUpdate> releaseTask(const TaskForUpdate& task);
    std::optional<TaskForUpdate> hideTask(const TaskForUpdate& task);
    std::optional<TaskForUpdate> markViewedTask(const TaskForUpdate& task);

    // @forbidden by Agent::validOperations();  NMAPS-13497
    std::optional<TaskForUpdate> showTask(const TaskForUpdate& task);

    std::optional<TaskForUpdate> changeTaskProcessingLvl(
        const TaskForUpdate& task,
        ProcessingLvl processingLvl,
        std::optional<Verdict> suggestedVerdict = std::nullopt);

    std::optional<TaskForUpdate> processingLevelDown(const TaskForUpdate& task);
    std::optional<TaskForUpdate> processingLevelUp(
        const TaskForUpdate& task,
        Verdict suggestedVerdict);

    std::optional<TaskForUpdate> changeTaskType(
        const TaskForUpdate& task,
        Type newType);

    std::optional<TaskForUpdate> changeTaskPosition(
        const TaskForUpdate& task,
        const geolib3::Point2& mercPoint,
        const TIds& aoiIdsForNewPosition);

    std::optional<TaskForUpdate> resolveTaskCascade(
        const TaskForUpdate& task,
        Resolution resolution,
        std::optional<TId> commentId = std::nullopt);

    std::optional<TaskForUpdate> openTask(
        const TaskForUpdate& task,
        std::optional<TId> commentId = std::nullopt);

    std::optional<TaskForUpdate> needInfoTask(
        const TaskForUpdate& task,
        TId commentId,
        std::optional<std::string> requestTemplate = std::nullopt);

    std::optional<TaskForUpdate> commentTask(
        TId taskId,
        TId commentId);

    std::optional<TaskForUpdate> deployTaskByIdCascade(
        TId id,
        chrono::TimePoint at);

    static TaskOperations validOperations(const Task& task, TUid uid);
    static TypesSet validNewTypes(const Task& task);
    static ProcessingLvlSet validNewProcessingLvls(const Task& task);
    static RejectReasonsSet validRejectReasons(const Task& task);

    static bool fromFbapi(const Task& task);

private:
    static bool canRequestInfo(const Task& task);

    GatewayRW gatewayRw_;
    TUid uid_;
};

} //namespace maps::wiki::social::feedback
