module analytics.api;

import handy_http_primitives;
import handy_http_handlers.path_handler : PathMapping, GetMapping;
import handy_http_data : writeJsonBody;
import std.datetime;

import profile.data;
import profile.service;
import profile.api : PROFILE_PATH;
import analytics.util;
import util.money;
import util.data;

@PathMapping(HttpMethod.GET, PROFILE_PATH ~ "/analytics/category-spend-time-series")
void handleGetCategorySpendTimeSeries(ref ServerHttpRequest request, ref ServerHttpResponse response) {
    auto ds = getProfileDataSource(request);
    serveJsonFromProperty(response, ds, "analytics.categorySpendTimeSeries");
}

@GetMapping(PROFILE_PATH ~ "/analytics/balance-time-series")
void handleGetBalanceTimeSeries(ref ServerHttpRequest request, ref ServerHttpResponse response) {
    import analytics.modules.balances;
    auto ds = getProfileDataSource(request);
    Currency currency = Currency.ofCode(request.getParamAs!string("currency", Currencies.USD.code));
    auto data = computeBalanceTimeSeries(ds, currency, getTimeRange(request));
    writeJsonBody(response, data);
}

@GetMapping(PROFILE_PATH ~ "/analytics/category-spend")
void handleGetCategorySpend(ref ServerHttpRequest request, ref ServerHttpResponse response) {
    import analytics.modules.category_spend;
    auto ds = getProfileDataSource(request);
    Currency currency = Currency.ofCode(request.getParamAs!string("currency", Currencies.USD.code));
    long categoryParentId = request.getParamAs!long("parentId", -1);
    Optional!ulong categoryParentIdOpt = categoryParentId == -1
        ? Optional!(ulong).empty()
        : Optional!(ulong).of(categoryParentId);
    auto data = computeCategorySpend(ds, currency, getTimeRange(request), categoryParentIdOpt);
    writeJsonBody(response, data);
}

/**
 * Helper method to serve JSON analytics data to a client by fetching it
 * directly from the user's profile properties table and writing it to the
 * response.
 * Params:
 *   response = The response to write to.
 *   ds = The datasource to serve data from.
 *   key = The name of the analytics property to read data from.
 */
private void serveJsonFromProperty(ref ServerHttpResponse response, ref ProfileDataSource ds, string key) {
    PropertiesRepository propsRepo = ds.getPropertiesRepository();
    string jsonStr = propsRepo.findProperty(key).orElse(null);
    if (jsonStr is null || jsonStr.length == 0) {
        response.status = HttpStatus.NOT_FOUND;
        response.writeBodyString("No data found for " ~ key);
    } else {
        response.writeBodyString(jsonStr, ContentTypes.APPLICATION_JSON);
    }
}

private TimeRange getTimeRange(in ServerHttpRequest request) {
    long fromTimestampMs = request.getParamAs!long("from", -1);
    long toTimestampMs = request.getParamAs!long("to", -1);
    return TimeRange(
        fromTimestampMs == -1
            ? Optional!(SysTime).empty()
            : Optional!(SysTime).of(toSysTime(fromTimestampMs)),
        toTimestampMs == -1
            ? Optional!(SysTime).empty()
            : Optional!(SysTime).of(toSysTime(toTimestampMs))
    );
}
