#pragma once

#include <maps/wikimap/mapspro/services/tasks_realtime/src/user_edits_metrics/lib/metrics.h>
#include <maps/wikimap/mapspro/services/tasks_realtime/src/user_edits_metrics/lib/util.h>
#include <maps/wikimap/mapspro/services/tasks_realtime/src/user_edits_metrics/lib/stat_utils/report_data_uploader.h>

#include <maps/wikimap/mapspro/libs/stat_client/include/report.h>

#include <maps/libs/chrono/include/time_point.h>
#include <maps/libs/introspection/include/comparison.h>

#include <chrono>
#include <optional>
#include <string>

namespace maps::wiki::user_edits_metrics {

using introspection::operator==;


class UserEditsProcessingTimesDimensions {
public:
    UserEditsProcessingTimesDimensions(
        chrono::TimePoint fielddate,
        Days days,
        std::string region,
        size_t userType,
        unsigned char percentile,
        bool inTrunk
    );

    auto introspect() const {
        return std::tie(fielddate_, days_, region_, userType_, percentile_, inTrunk_);
    }

    static void printHeader(csv::OutputStream& os);
    void print(csv::OutputStream& os) const;

    std::map<std::string, std::string> keyValues(pqxx::transaction_base& txn) const;

private:
    std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> fielddate_;
    Days days_;
    std::string region_;
    size_t userType_;
    unsigned char percentile_;
    bool inTrunk_;
};


struct UserEditsProcessingTimesMeasures {
    std::optional<std::chrono::seconds> cameras;
    std::optional<std::chrono::seconds> carparks;
    std::optional<std::chrono::seconds> geocoder;
    std::optional<std::chrono::seconds> graph;
    std::optional<std::chrono::seconds> mtrExport;
    std::optional<std::chrono::seconds> renderer;
    std::optional<std::chrono::seconds> bicycleGraph;
    std::optional<std::chrono::seconds> pedestrianGraph;
    std::optional<std::chrono::seconds> approved;
    std::optional<std::chrono::seconds> exported;
    std::optional<std::chrono::seconds> inStable;
    std::optional<std::chrono::seconds> resolved;

    static void printHeader(csv::OutputStream& os);
    void print(csv::OutputStream& os) const;

    std::map<std::string, std::string> keyValues() const;
};


class UserEditsProcessingTimesReport:
    public stat_client::Report<
        UserEditsProcessingTimesDimensions,
        UserEditsProcessingTimesMeasures,
        stat_client::Scale::Continual
    >,
    public ReportDataUploader
{
public:
    UserEditsProcessingTimesReport();
    void add(const MetricVec& metrics);

    void upload(pqxx::transaction_base& txn) const;
};

} // namespace maps::wiki::user_edits_metrics
