package io.delphiplatform.api.v3.view;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.NativeWebRequest;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;

import io.delphiplatform.api.v3.constant.ApplicationConstants;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.model.Playlist;
import io.delphiplatform.api.v3.model.Playlists;
import io.delphiplatform.api.v3.model.SortOrder;
import io.delphiplatform.api.v3.validation.ExactMatchesForSingleValue;
import io.delphiplatform.api.v3.view.interceptor.OnlyDeclaredParams;

@Validated
public interface PlaylistsApi {

    default Optional<NativeWebRequest> getRequest() {
        return Optional.empty();
    }

    /**
     * GET /playlists/{playlist_id} : Query for a single Playlist Resource route for getting a single &#x60;Playlist&#x60; with filtering based on
     * provided parameters
     *
     * @param playlistId (required)
     * @return &#x60;Playlist&#x60; response object (status code 200) or 400 Invalid Input Response (status code 400) or 401 Unauthorized
     * (AuthError) Response (status code 401) or 404 Not Found Error Response (status code 404) or 500 Internal Error Response (status code 500)
     */
    @OnlyDeclaredParams
    @RequestMapping(value = "/playlists/{playlist_id}",
        produces = {"application/json"},
        method = RequestMethod.GET)
    default ResponseEntity<Playlist> playlistsGet(
        @PathVariable("playlist_id") String playlistId
    ) {
        return findOne(playlistId);
    }

    ResponseEntity<Playlist> findOne(String playlistId);


    /**
     * GET /playlists : Search for Playlists Resource route for getting a list of &#x60;Playlists&#x60; with filtering based on provided
     * parameters
     *
     * @param dspUnused preserved for params validation
     * @param limit     The maximum number of &#x60;items&#x60; to return in a single request. (optional)
     * @param offset    The number of &#x60;items&#x60; to offset for pagination. (optional)
     * @param sortBy    Field name by which to sort the data. (optional)
     * @param sortOrder Direction to sort the data. Default: &#x60;desc&#x60; if &#x60;sort_by&#x60; provided. (optional, default to desc)
     * @return &#x60;Playlists&#x60; response object (status code 200) or 400 Invalid Input Response (status code 400) or 401 Unauthorized
     * (AuthError) Response (status code 401) or 500 Internal Error Response (status code 500)
     */
    @RequestMapping(value = "/playlists",
        produces = {"application/json"},
        method = RequestMethod.GET)
    default ResponseEntity<Playlists> playlistsSearch(
        @RequestParam(value = "dsp", required = false) List<String> dspUnused, //preserved for params validation
        @Min(0) @Max(ApplicationConstants.MAX_PAGE_SIZE)
        @RequestParam(value = "limit", required = false) Integer limit,
        @Min(0) @RequestParam(value = "offset", required = false) Integer offset,
        @ExactMatchesForSingleValue(message = ApplicationConstants.ERROR_MESSAGE_SORT_BY_PARAMETER, anyOf = {
            "country_code", "dsp_playlist_id", "name", "num_tracks", "playlist_id", "playlist_type", "rank", "uri"
        })
        @RequestParam(value = "sort_by", required = false) String sortBy,
        @RequestParam(value = "sort_order", required = false, defaultValue = "desc") SortOrder sortOrder
    ) {
        return getSearchData(Collections.singletonList(DspConstants.AMAZON), limit, offset, sortBy, sortOrder);
    }

    ResponseEntity<Playlists> getSearchData(List<String> dsp, Integer limit, Integer offset, String sortBy,
        SortOrder sortOrder);

}
