#pragma once

#include <maps/wikimap/mapspro/libs/assessment/include/common.h>
#include <maps/libs/chrono/include/time_point.h>
#include <maps/libs/common/include/enum_bitset.h>
#include <maps/libs/enum_io/include/enum_io_fwd.h>
#include <maps/libs/introspection/include/comparison.h>

namespace maps::wiki::assessment {

using introspection::operator<;
using introspection::operator==;

struct Entity
{
    enum class Domain {
        Edits,
        Feedback,
        Moderation,
        Tracker
    };

    std::string id;
    Domain domain;

    auto introspect() const { return std::tie(id, domain); }
};
DECLARE_ENUM_IO(Entity::Domain);

struct Action
{
    std::string name;
    TUid by;
    chrono::TimePoint at;

    auto introspect() const { return std::tie(at, name, by); }
};

struct Unit
{
    TId id;
    Entity entity;
    Action action;

    auto introspect() const { return std::tie(id, entity, action); }
};
using UnitVec = std::vector<Unit>;

enum class Qualification
{
    Basic,
    Expert,
};
DECLARE_ENUM_IO(Qualification);

struct Grade
{
    enum class Value {
        Incorrect,
        Correct
    };

    TId id;
    TUid gradedBy;
    chrono::TimePoint gradedAt;
    Value value;
    std::optional<std::string> comment;
    Qualification qualification;

    auto introspect() const { return std::tie(id, gradedBy, gradedAt, value, comment, qualification); }
};
using GradeVec = std::vector<Grade>;
DECLARE_ENUM_IO(Grade::Value);

enum class UnitStatus {
    Correct,
    Incorrect,
    Fixed
};
DECLARE_ENUM_IO(UnitStatus);

enum class GradeStatus {
    Confirmed,
    Refuted,
    RefutationAccepted
};
DECLARE_ENUM_IO(GradeStatus);

enum class UnitPermission : unsigned {
    Fixable,
    RefutationAcceptable,
    EnumBitsetFlagsEnd,
};
using UnitPermissionFlags = maps::common::EnumBitset<UnitPermission>;

struct GradedUnit : public Unit
{
    GradeVec grades;
    UnitPermissionFlags permissions;

    auto introspect() const { return std::make_tuple(Unit::introspect(), grades, permissions); }
};
using GradedUnitVec = std::vector<GradedUnit>;

enum class GradesVisibility {
    My,
    MyOrReceivedByMe,
    All
};

} // namespace maps::wiki::assessment
