#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature.h>
#include <maps/libs/geolib/include/polyline.h>

#include <string_view>

namespace maps::mrc::graph_coverage_export {

// Each of the following struct is a wrapper for corresponding YT-table row

struct Region {
    static constexpr std::string_view YT_TABLE_NAME = "regions";

    int32_t geoId;
    std::string name;

    template<class T>
    static auto introspect(T& t)
    {
        return std::tie(t.geoId, t.name);
    }

    static auto columns() {
        return std::make_tuple(col::GEO_ID, col::NAME);
    }
};

struct GraphLength {

    static constexpr std::string_view YT_TABLE_NAME = "graph_length";

    int32_t geoId;
    uint8_t fc;
    uint8_t isToll;
    uint8_t privateArea;
    uint8_t graphType;
    double length;

    template<class T>
    static auto introspect(T& t)
    {
        return std::tie(t.geoId, t.fc, t.isToll, t.privateArea, t.graphType, t.length);
    }

    static auto columns() {
        return std::make_tuple(col::GEO_ID, col::FC, col::IS_TOLL, col::PRIVATE_AREA,
            col::GRAPH_TYPE, col::LENGTH);
    }
};


struct EdgeData {

    static constexpr std::string_view YT_TABLE_NAME = "graph_coverage_edge_data";

    uint8_t fc;
    bool isToll;
    geolib3::Polyline2 geom;
    std::vector<int32_t> geoIds;
    bool privateArea;
    db::Features features;
    uint8_t graphType;

    template<class T>
    static auto introspect(T& t)
    {
        return std::tie(t.fc, t.isToll, t.geom, t.geoIds, t.privateArea, t.features,
            t.graphType);
    }

    static auto columns() {
        return std::make_tuple(col::FC, col::IS_TOLL, col::GEOM, col::GEO_IDS,
            col::PRIVATE_AREA, col::FEATURES, col::GRAPH_TYPE);
    }
};

struct CoverageEdgeData {
    std::optional<uint8_t> dataset;  // std::nullopt for all datasets
    uint8_t fc;
    uint8_t isToll;
    int32_t geoId;
    uint8_t privateArea;
    uint8_t graphType;
    uint8_t cameraDeviation;
    double length;

    template<class T>
    static auto introspect(T& t)
    {
        return std::tie(t.dataset, t.fc, t.isToll, t.geoId,
            t.privateArea, t.graphType, t.cameraDeviation, t.length);
    }

    static auto columns() {
        return std::make_tuple(col::DATASET, col::FC, col::IS_TOLL, col::GEO_ID,
            col::PRIVATE_AREA, col::GRAPH_TYPE, col::CAMERA_DEVIATION, col::LENGTH);
    }
};

struct IntervalCoverageEdgeData {

    static constexpr std::string_view YT_TABLE_NAME = "graph_coverage";

    CoverageEdgeData coverageEdgeData;
    int32_t fromDate;
    int32_t toDate;
    int32_t actualizationDate;

    template<class T>
    static auto introspect(T& t)
    {
        return std::tuple_cat(
            CoverageEdgeData::introspect(t.coverageEdgeData),
            std::tie(t.fromDate, t.toDate, t.actualizationDate)
        );
    }

    static auto columns() {
        return std::tuple_cat(
            CoverageEdgeData::columns(),
            std::make_tuple(col::FROM_DATE, col::TO_DATE, col::ACTUALIZATION_DATE));
    }
};

enum class CoverageAgeCategory {
    Age_0_7,
    Age_7_30,
    Age_30_90,
    Age_90_180,
    Age_180,
};

struct DatedCoverageEdgeData {
    static constexpr std::string_view YT_TABLE_NAME = "graph_coverage_timeline";

    CoverageEdgeData coverageEdgeData;
    uint8_t ageCategory;
    int32_t date;

    template<class T>
    static auto introspect(T& t)
    {
        return std::tuple_cat(
            CoverageEdgeData::introspect(t.coverageEdgeData),
            std::tie(t.date, t.ageCategory)
        );
    }

    static auto columns() {
        return std::tuple_cat(
            CoverageEdgeData::columns(),
            std::make_tuple(col::DATE, col::AGE_CATEGORY));
    }
};

} // namespace maps::mrc::graph_coverage_export
