package io.delphiplatform.api.v3.view;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;
import java.util.concurrent.CompletableFuture;

import javax.transaction.NotSupportedException;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.bigtable.BigtableTrackPositionService;
import io.delphiplatform.api.v3.bigtable.BigtableTrackPositionSummaryService;
import io.delphiplatform.api.v3.model.IncludeTracklistPlaylist;
import io.delphiplatform.api.v3.model.trackposition.PlaylistTrackPosition;
import io.delphiplatform.api.v3.model.trackposition.PlaylistTrackPositionAddition;
import io.delphiplatform.api.v3.model.trackposition.PlaylistTrackPositionAdditions;
import io.delphiplatform.api.v3.model.trackposition.PlaylistTrackPositionSummaries;
import io.delphiplatform.api.v3.model.trackposition.PlaylistTrackPositionSummary;
import io.delphiplatform.api.v3.model.trackposition.PlaylistTrackPositions;
import io.delphiplatform.api.v3.view.util.Params;
import io.delphiplatform.api.v3.view.util.ParamsHelper;
import lombok.extern.slf4j.Slf4j;

@Deprecated
@Controller
@RequestMapping("${spring.data.rest.base-path:/v3}")
@Slf4j
public class TrackPositionsApiController implements TrackPositionsApi {

    private final ParamsHelper paramsHelper;
    private final BigtableTrackPositionService trackPositionService;
    private final BigtableTrackPositionSummaryService trackPositionSummaryService;

    public TrackPositionsApiController(
        ParamsHelper paramsHelper,
        BigtableTrackPositionService trackPositionService,
        BigtableTrackPositionSummaryService trackPositionSummaryService
    ) {
        this.paramsHelper = paramsHelper;
        this.trackPositionService = trackPositionService;
        this.trackPositionSummaryService = trackPositionSummaryService;
    }

    @Override
    public CompletableFuture<ResponseEntity<PlaylistTrackPositions>> getPlaylistTrackPositions(Params params) {
        try {
            CompletableFuture<List<PlaylistTrackPosition>> models = trackPositionService
                .getPlaylistTrackPositionModels(params);
            return models.thenApply(r -> ResponseEntity.ok(new PlaylistTrackPositions()
                .items(r)
                .nextCursor(params.getNextCursor())
                .count(r.size())));
        } catch (NotSupportedException e) {
            log.error("Error while getting playlist positions.", e);
            throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, e.getMessage());
        }
    }

    @Override
    public CompletableFuture<ResponseEntity<PlaylistTrackPositionSummaries>> getPlaylistTrackPositionsSummaries(
        Params params) {
        try {
            CompletableFuture<List<PlaylistTrackPositionSummary>> models = trackPositionSummaryService
                .getPlaylistTrackPositionModels(params);
            return models.thenApply(r -> ResponseEntity.ok(new PlaylistTrackPositionSummaries()
                .items(r)
                .nextCursor(params.getNextCursor())
                .count(r.size())));
        } catch (NotSupportedException e) {
            log.error("Error while getting playlist position summaries.", e);
            throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, e.getMessage());
        }
    }

    @Override
    public CompletableFuture<ResponseEntity<PlaylistTrackPositionAdditions>> getPlaylistTrackPositionsAdditions(
        Params params) {
        CompletableFuture<List<PlaylistTrackPositionAddition>> models = null;
        try {
            models = trackPositionService
                .getPlaylistTrackPositionAdditionModels(params);
        } catch (NotSupportedException e) {
            log.error("Error while getting playlist position summaries.", e);
            throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, e.getMessage());
        }
        return models.thenApply(r -> ResponseEntity.ok(new PlaylistTrackPositionAdditions()
            .items(r)
            .nextCursor(params.getNextCursor())
            .count(r.size())));
    }

    @Override
    public void validateParams(Params params) {
        String msg = null;

        if (CollectionUtils.isEmpty(params.getArtistId())
            && CollectionUtils.isEmpty(params.getPlaylistId())
            && CollectionUtils.isEmpty(params.getChartId())
            && CollectionUtils.isEmpty(params.getIsrc())) {
            msg = "Missing at least one identifiying parameter from set: [artist_id, playlist_id, isrc]";
        }

        if (params.getInclude() != null
            && params.getInclude().contains(IncludeTracklistPlaylist.STREAMS.getValue())
            && CollectionUtils.isEmpty(params.getIsrc())) {
            msg = "Missing required parameter `isrc` when providing `include=streams`";
        }

        if (msg != null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, msg);
        }
    }

    @Override
    public Params loadAdditionalParams(Params params) {
        return paramsHelper.loadAdditionalParamsForTrackPositions(params);
    }
}
