package io.delphiplatform.api.v3.bigtable;

import javax.transaction.NotSupportedException;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.bigtable.config.RowKeyGroup;
import io.delphiplatform.api.v3.bigtable.config.RowKeyPrefix;
import io.delphiplatform.api.v3.model.AggBy;
import io.delphiplatform.api.v3.model.SubsetParam;
import io.delphiplatform.api.v3.view.util.Params;

/**
 * Container for the logic to determine which RowKeyPrefix to use based on the RowKeyGroup and Params
 */
public class RowKeyPrefixHelper {

    private final Params params;
    private final RowKeyGroup rowKeyGroup;
    private final String missingMinimumParamsMsg = "Missing minimum provided parameters to get prefix";

    /**
     * @param params      parameters from client request
     * @param rowKeyGroup row key group determined by request logic
     */
    public RowKeyPrefixHelper(Params params, RowKeyGroup rowKeyGroup) {
        this.params = params;
        this.rowKeyGroup = rowKeyGroup;
    }

    /**
     * @return a row key prefix based on specified params and row key group
     */
    public RowKeyPrefix getPrefix() throws NotSupportedException {
        RowKeyPrefix result;
        switch (rowKeyGroup) {
            case STREAM:
                result = getPrefixStream();
                break;
            case PLAYLIST:
                result = getPrefixPlaylistPosition();
                break;
            case CHARTMETRIC:
                result = getPrefixChartmetric();
                break;
            case VIDEO:
                result = getPrefixVideo();
                break;
            case TIKTOK:
                result = getPrefixTikTok();
                break;
            case FACT_PLAYLIST_DAILY:
                result = getPrefixFactPlaylistDaily();
                break;
            case PLAYLIST_FOLLOWERS_DAILY:
                result = getPrefixPlaylistFollowersDaily();
                break;
            case BRAND_TAGGING:
                result = getPrefixBrandTagging();
                break;
            case TIKTOK_TOP_ISRC_TRACKS:
                result = getPrefixTikTokTopIsrcSounds();
                break;
            default:
                throw new NotSupportedException(missingMinimumParamsMsg);
        }
        return result;
    }

    private RowKeyPrefix getPrefixTikTok() {
        return RowKeyPrefix.ISRC_TIKTOK_CONTENT_TYPE_DATE;
    }

    private RowKeyPrefix getPrefixStream() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getProjectNumbers())) {
            return RowKeyPrefix.PROJECT;
        }
        if (CollectionUtils.isNotEmpty(params.getProductId())) {
            return RowKeyPrefix.PRODUCT_DATE;
        }
        if (CollectionUtils.isNotEmpty(params.getProductFamilyIds())) {
            return RowKeyPrefix.PRODUCT_FAMILY;
        }
        if (CollectionUtils.isNotEmpty(params.getPlaylistId())) {
            return getPrefixStreamByPlaylist();
        }
        if (CollectionUtils.isNotEmpty(params.getIsrc())) {
            return getPrefixStreamByIsrc();
        }
        if (CollectionUtils.isNotEmpty(params.getArtistId())) {
            return RowKeyPrefix.ARTIST_DATE;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    private RowKeyPrefix getPrefixPlaylistPosition() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getPlaylistId()) && CollectionUtils.isNotEmpty(params.getIsrc())) {
            return RowKeyPrefix.PLAYLIST_ISRC_DATE;
        }
        if (CollectionUtils.isNotEmpty(params.getPlaylistId())) {
            return RowKeyPrefix.PLAYLIST_DATE_ISRC;
        }
        if (CollectionUtils.isNotEmpty(params.getIsrc()) && CollectionUtils.isNotEmpty(params.getDsp())) {
            return RowKeyPrefix.DSP_ISRC_DATE_PLAYLIST;
        }
        if (CollectionUtils.isNotEmpty(params.getIsrc())) {
            return RowKeyPrefix.ISRC_DATE_PLAYLIST;
        }
        if (CollectionUtils.isNotEmpty(params.getDsp())) {
            return RowKeyPrefix.DSP_ISRC_DATE_PLAYLIST;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    private RowKeyPrefix getPrefixFactPlaylistDaily() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getPlaylistId()) && CollectionUtils.isNotEmpty(params.getCountryCode())) {
            return RowKeyPrefix.PLAYLIST_COUNTRY_CODE_DATE;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    private RowKeyPrefix getPrefixPlaylistFollowersDaily() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getPlaylistId())) {
            return RowKeyPrefix.PLAYLIST_DATE;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    private RowKeyPrefix getPrefixBrandTagging() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getTrackId())) {
            return RowKeyPrefix.TRACK;
        }
        if (CollectionUtils.isNotEmpty(params.getUpc())) {
            return RowKeyPrefix.UPC_BRAND;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    private RowKeyPrefix getPrefixTikTokTopIsrcSounds() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getIsrc()) && params.getStartDate() != null && params.getEndDate() != null) {
            return RowKeyPrefix.ISRC_DATE;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    private RowKeyPrefix getPrefixChartmetric() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getArtistId())) {
            return RowKeyPrefix.ARTIST;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    private RowKeyPrefix getPrefixVideo() throws NotSupportedException {
        if (CollectionUtils.isNotEmpty(params.getProductFamilyIds())) {
            return RowKeyPrefix.PRODUCT_FAMILY_CONTENT_TYPE_DATE;
        }
        if (CollectionUtils.isNotEmpty(params.getVideoIds())) {
            return RowKeyPrefix.VIDEO_DATE;
        }
        if (CollectionUtils.isNotEmpty(params.getIsrc()) &&
            CollectionUtils.isNotEmpty(params.getYouTubeContentTypes())) {
            return RowKeyPrefix.ISRC_CONTENT_DATE;
        }
        if (CollectionUtils.isNotEmpty(params.getIsrc()) &&
            CollectionUtils.isEmpty(params.getYouTubeContentTypes())) {
            return RowKeyPrefix.ISRC_DATE;
        }
        if (CollectionUtils.isNotEmpty(params.getProjectNumbers())) {
            return RowKeyPrefix.PROJECT_CONTENT_DATE;
        }
        throw new NotSupportedException(missingMinimumParamsMsg);
    }

    /**
     * Assumes we have {@code params.playlistId}
     */
    private RowKeyPrefix getPrefixStreamByPlaylist() {
        if (CollectionUtils.isNotEmpty(params.getIsrc())) {
            return RowKeyPrefix.PLAYLIST_ISRC_DATE;
        }
        if (AggBy.ISRC == params.getAggBy()) {
            return RowKeyPrefix.PLAYLIST_DATE_ISRC;
        }
        if (CollectionUtils.isNotEmpty(params.getArtistId())) {
            return RowKeyPrefix.ARTIST_PLAYLIST_DATE;
        }
        return RowKeyPrefix.PLAYLIST_DATE;
    }

    /**
     * Assumes we have {@code params.isrc}
     */
    private RowKeyPrefix getPrefixStreamByIsrc() {
        if (SubsetParam.PLAYLISTS == params.getSubset()) {
            return RowKeyPrefix.ISRC_DATE_PLAYLIST;
        }
        return RowKeyPrefix.ISRC_DATE;
    }
}
