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.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import javax.transaction.NotSupportedException;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.util.model.ModelUtils;
import io.delphiplatform.api.v3.bigtable.BigtableTracksBrandTaggingService;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.model.IncludeTracks;
import io.delphiplatform.api.v3.model.Track;
import io.delphiplatform.api.v3.model.TrackSimple;
import io.delphiplatform.api.v3.model.Tracks;
import io.delphiplatform.api.v3.model.TracksBrandTagging;
import io.delphiplatform.api.v3.rdb.service.TrackService;
import io.delphiplatform.api.v3.view.util.Params;
import lombok.extern.slf4j.Slf4j;

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

    private final TrackService trackService;
    private final BigtableTracksBrandTaggingService bigtableTracksBrandTaggingService;

    public TracksApiController(
        TrackService trackService,
        BigtableTracksBrandTaggingService bigtableTracksBrandTaggingService
    ) {
        this.trackService = trackService;
        this.bigtableTracksBrandTaggingService = bigtableTracksBrandTaggingService;
    }

    @Override
    public ResponseEntity<Track> findOne(String trackId,
        Set<IncludeTracks> include) {
        return ResponseEntity.ok(trackService.findOne(trackId, include));
    }

    @Override
    public ResponseEntity<Tracks> getSearchData(Params params) {
        List<TrackSimple> items = trackService.find(params);
        return ResponseEntity.ok(new Tracks().items(items).count(items.size()));
    }

    @Override
    public CompletableFuture<ResponseEntity<TracksBrandTagging>> getTracksBrandsTagging(Params params) {
        if (CollectionUtils.isNotEmpty(params.getTrackId())) {
            Set<String> trackIdsWithBadDsp = params.getTrackId().stream()
                .filter(trackId -> !ModelUtils.isTrackOfDsp(trackId, DspConstants.APPLE)
                    && !ModelUtils.isTrackOfDsp(trackId, DspConstants.SPOTIFY))
                .collect(Collectors.toSet());

            if (!trackIdsWithBadDsp.isEmpty()) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
                    "track_id parameter has unsupported value. Must be a track id with dsp prefix ('spotify|apple_xxx'). "
                        + "You provided: " + trackIdsWithBadDsp);
            }
        }

        try {
            CompletableFuture<TracksBrandTagging> models = bigtableTracksBrandTaggingService.getTrackBrandTaggingModels(params);

            return models.thenApply(ResponseEntity::ok);
        } catch (NotSupportedException e) {
            log.error("Error while getting brand tagging info.", e);
            throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, e.getMessage());
        }
    }
}
