#pragma once

#include "ride.h"

#include <maps/libs/sql_chemistry/include/gateway.h>

namespace maps::mrc::db {

namespace table {

using namespace sql_chemistry;

struct Ride : Table<db::Ride> {
    static constexpr std::string_view name_{"rides.ride"sv};

    static constexpr BigSerialKey rideId{"ride_id"sv, name_};
    static constexpr StringColumn userId{"user_id"sv, name_};
    static constexpr TimePointColumn startTime{"start_time"sv, name_};
    static constexpr TimePointColumn endTime{"end_time"sv, name_};
    static constexpr StringColumn sourceId{"source_id"sv, name_};
    static constexpr MercatorColumn<geolib3::Polyline2> track{"track"sv, name_};
    static constexpr DoubleColumn distanceInMeters{"distance_in_meters"sv,
                                                   name_};
    static constexpr NumericColumn<size_t> photos{"photos"sv, name_};
    static constexpr TimePointColumn uploadStartTime{"upload_start_time"sv,
                                                     name_};
    static constexpr TimePointColumn uploadEndTime{"upload_end_time"sv, name_};
    static constexpr BooleanColumn isDeleted{"is_deleted"sv, name_};
    static constexpr NullableBooleanColumn showAuthorship{"show_authorship"sv,
                                                          name_};
    static constexpr NullableEnumColumn<RideStatus> status{"status"sv, name_};
    static constexpr NullableStringColumn clientId{"client_id"sv, name_};
    static constexpr NullableNumericColumn<size_t> publishedPhotos{
        "published_photos"sv, name_};
    static constexpr XminColumn xmin{name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};

    static constexpr auto columns_()
    {
        return std::tie(rideId,
                        userId,
                        startTime,
                        endTime,
                        sourceId,
                        track,
                        distanceInMeters,
                        photos,
                        uploadStartTime,
                        uploadEndTime,
                        isDeleted,
                        showAuthorship,
                        status,
                        clientId,
                        publishedPhotos,
                        xmin,
                        txnId);
    }
};

struct RideLiteView : Table<db::RideLiteView> {
    static constexpr std::string_view name_{"rides.ride"sv};

    static constexpr BigSerialKey rideId{"ride_id"sv, name_};
    static constexpr StringColumn userId{"user_id"sv, name_};
    static constexpr TimePointColumn startTime{"start_time"sv, name_};
    static constexpr TimePointColumn endTime{"end_time"sv, name_};
    static constexpr DoubleColumn distanceInMeters{"distance_in_meters"sv, name_};
    static constexpr NumericColumn<size_t> photos{"photos"sv, name_};
    static constexpr NullableNumericColumn<size_t> publishedPhotos{
        "published_photos"sv, name_};
    static constexpr BooleanColumn isDeleted{"is_deleted"sv, name_};

    static constexpr auto columns_()
    {
        return std::tie(rideId,
                        userId,
                        startTime,
                        endTime,
                        distanceInMeters,
                        photos,
                        publishedPhotos,
                        isDeleted);
    }
};


struct DeletedInterval : Table<db::DeletedInterval> {
    static constexpr std::string_view name_{"rides.deleted_interval"sv};

    static constexpr BigSerialKey id{"deleted_interval_id"sv, name_};
    static constexpr StringColumn userId{"user_id"sv, name_};
    static constexpr StringColumn sourceId{"source_id"sv, name_};
    static constexpr TimePointColumn startedAt{"started_at"sv, name_};
    static constexpr TimePointColumn endedAt{"ended_at"sv, name_};
    static constexpr TimePointColumn createdAt{"created_at"sv, name_};
    static constexpr NullableStringColumn clientRideId{"client_ride_id"sv,
                                                       name_};

    static constexpr auto columns_()
    {
        return std::tie(
            id, userId, sourceId, startedAt, endedAt, createdAt, clientRideId);
    }
};

struct RideHypothesis : Table<db::RideHypothesis> {
    static constexpr std::string_view name_{"rides.ride_hypothesis"sv};

    static constexpr NumericColumn<TId> rideId{"ride_id"sv, name_};
    static constexpr NumericColumn<TId> hypothesisId{"hypothesis_id"sv, name_};

    static constexpr auto columns_() { return std::tie(rideId, hypothesisId); }
};

}  // namespace table

using RideGateway = db::TxnIdGatewayBase<table::Ride>;
using RideLiteViewGateway = sql_chemistry::Gateway<table::RideLiteView>;
using DeletedIntervalGateway = sql_chemistry::Gateway<table::DeletedInterval>;
using RideHypothesisGateway = sql_chemistry::Gateway<table::RideHypothesis>;

}  // namespace maps::mrc::db
