package jikan

import (
	"context"
	"fmt"
	"net/url"
	"strconv"
	"strings"
)

// SearchAdvanced performs a filtered anime search with type, status, ordering, genre filters, and studio (producer) filters.
func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, orderBy, sort string, genres []int, studioID int, sfw bool, page, limit int) (SearchResult, error) {
	if page < 1 {
		page = 1
	}
	if limit < 0 {
		limit = 0
	}

	genresParam := ""
	if len(genres) > 0 {
		ids := make([]string, len(genres))
		for i, g := range genres {
			ids[i] = strconv.Itoa(g)
		}
		genresParam = strings.Join(ids, ",")
	}

	cacheKey := fmt.Sprintf("search:%s:%s:%s:%s:%s:%s:%d:%v:%d:%d", query, animeType, status, orderBy, sort, genresParam, studioID, sfw, page, limit)

	var result SearchResponse
	reqURL := fmt.Sprintf("%s/anime?page=%d", c.baseURL, page)
	if sfw {
		reqURL += "&sfw=true"
	}
	if query != "" {
		reqURL += "&q=" + url.QueryEscape(query)
	}
	if animeType != "" {
		reqURL += "&type=" + url.QueryEscape(animeType)
	}
	if status != "" {
		reqURL += "&status=" + url.QueryEscape(status)
	}
	if studioID > 0 {
		reqURL += "&producers=" + strconv.Itoa(studioID)
	}
	if orderBy != "" {
		reqURL += "&order_by=" + url.QueryEscape(orderBy)
	}
	if sort != "" {
		reqURL += "&sort=" + url.QueryEscape(sort)
	}
	if genresParam != "" {
		reqURL += "&genres=" + genresParam
	}
	if limit > 0 {
		reqURL += fmt.Sprintf("&limit=%d", limit)
	}

	if err := c.getWithCache(ctx, cacheKey, shortCacheTTL, reqURL, &result); err != nil {
		return SearchResult{}, err
	}

	return SearchResult{
		Animes:      result.Data,
		HasNextPage: result.Pagination.HasNextPage,
	}, nil
}

// GetTopAnime returns the top-rated anime list for a given page.
func (c *Client) GetTopAnime(ctx context.Context, page int) (TopAnimeResult, error) {
	if page < 1 {
		page = 1
	}
	cacheKey := fmt.Sprintf("top:%d", page)

	var result TopAnimeResponse
	reqURL := fmt.Sprintf("%s/top/anime?page=%d", c.baseURL, page)

	if err := c.getWithCache(ctx, cacheKey, shortCacheTTL, reqURL, &result); err != nil {
		return TopAnimeResult{}, err
	}

	return TopAnimeResult{
		Animes:      result.Data,
		HasNextPage: result.Pagination.HasNextPage,
	}, nil
}

// GetAnimeGenres returns list of all anime genres, cached long-term.
func (c *Client) GetAnimeGenres(ctx context.Context) ([]Genre, error) {
	const cacheKey = "anime_genres"

	var result GenresResponse
	reqURL := fmt.Sprintf("%s/genres/anime", c.baseURL)

	if err := c.getWithCache(ctx, cacheKey, longCacheTTL, reqURL, &result); err != nil {
		return nil, err
	}

	return result.Data, nil
}
