#pragma once

#include <yandex/maps/wiki/tasks/common.h>
#include <yandex/maps/wiki/common/extended_xml_doc.h>
#include <yandex/maps/wiki/common/pg_utils.h>
#include <yandex/maps/wiki/common/pgpool3_helpers.h>
#include <maps/libs/chrono/include/days.h>
#include <maps/libs/pgpool/include/pgpool3.h>
#include <maps/libs/common/include/exception.h>

#include <pqxx/pqxx>

#include <chrono>
#include <iosfwd>
#include <string>

namespace maps::wiki::tasks {

std::ostream& operator<<(std::ostream& out, FrozenState state);

bool isFrozen(pqxx::transaction_base& txn, TaskId taskId);

void freezeTask(pqxx::transaction_base& txn, TaskId taskId);

void unfreezeTask(pqxx::transaction_base& txn, TaskId taskId);

struct TaskNotFoundException : public maps::Exception
{
    TaskNotFoundException(TaskId taskId_)
        : maps::Exception("No task found for id  " + std::to_string(taskId_))
        , taskId(taskId_)
    {
    }
    const TaskId taskId;
};

/**
Returns common attributes for the tasks of specific type
*/
common::Attributes attributesForTaskType(
    pqxx::transaction_base& txn,
    const std::string& taskType);

/**
Concatenates common attributes for the tasks of specific type
*/
void concatenateAttributesForTaskType(
    pqxx::transaction_base& txn,
    const std::string& taskType,
    const common::Attributes& attributes);

std::string makeTaskTag(TaskId taskId);

void deleteOldTmpFiles(const std::string& baseDir, chrono::Days days = chrono::Days(30));

/**
Task explicit status manipulation helpers.
Set given status for given task in database if it fits task flow logic.
*/
common::PoolHolder corePoolHolder(const common::ExtendedXmlDoc& config);
bool setOverriddenStatus(
    pqxx::transaction_base& txn, TaskId taskId, TaskStatus taskStatus, bool force = false);
bool setOverriddenStatus(
    pgpool3::Pool& pool, TaskId taskId, TaskStatus taskStatus, bool force = false);
bool setOverriddenStatus(
    const common::ExtendedXmlDoc& config, TaskId taskId, TaskStatus taskStatus, bool force = false);

std::optional<TaskStatus> getOverriddenStatus(pqxx::transaction_base& txn, TaskId taskId);
std::optional<TaskStatus> getOverriddenStatus(pgpool3::Pool& txn, TaskId taskId);

} // namespace maps::wiki::tasks
