package com.pandoli365.bibimbap.controller;

import com.pandoli365.bibimbap.data.GameData;
import com.pandoli365.bibimbap.data.SearchCriteria;
import com.pandoli365.bibimbap.data.TagData;
import com.pandoli365.bibimbap.mapper.GamesMapper;
import com.pandoli365.bibimbap.mapper.TagsMapper;
import com.pandoli365.bibimbap.util.TagSanitizer;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

@Controller
public class SearchController {

    private static final Set<String> SORT_KEYS = Set.of("latest", "likes", "views", "reviews", "rating", "relevance");
    private static final Set<String> TAG_MODES = Set.of("and", "or");

    private final GamesMapper gamesMapper;
    private final TagsMapper tagsMapper;

    public SearchController(GamesMapper gamesMapper, TagsMapper tagsMapper) {
        this.gamesMapper = gamesMapper;
        this.tagsMapper = tagsMapper;
    }

    @GetMapping("/games/search")
    public String search(
            @RequestParam(name = "keyword", required = false) String keyword,
            @RequestParam(name = "creator", required = false) String creator,
            @RequestParam(name = "tags", required = false) String tagsCsv,
            @RequestParam(name = "tagMode", required = false, defaultValue = "and") String tagMode,
            @RequestParam(name = "sort", required = false, defaultValue = "latest") String sort,
            @RequestParam(name = "jam", required = false) String jam,
            Model model
    ) {
        String normalizedKeyword = trimToNull(keyword);
        String normalizedCreator = trimToNull(creator);

        List<String> tagSlugs = parseTagSlugs(tagsCsv);

        String normalizedTagMode = TAG_MODES.contains(tagMode) ? tagMode : "and";
        String normalizedSort = SORT_KEYS.contains(sort) ? sort : "latest";

        String normalizedJam = trimToNull(jam);

        SearchCriteria criteria = new SearchCriteria();
        criteria.setKeyword(normalizedKeyword);
        criteria.setCreator(normalizedCreator);
        criteria.setTags(tagSlugs.isEmpty() ? null : tagSlugs);
        criteria.setTagCount(tagSlugs.size());
        criteria.setTagMode(normalizedTagMode);
        criteria.setSort(normalizedSort);
        criteria.setJamSlug(normalizedJam);

        List<GameData> games = gamesMapper.searchGamesAdvanced(criteria);
        List<TagData> availableTags = tagsMapper.listActiveByType("GAME", null);

        model.addAttribute("games", games);
        model.addAttribute("searching", true);
        model.addAttribute("searchKeyword", normalizedKeyword == null ? "" : normalizedKeyword);
        model.addAttribute("searchCreator", normalizedCreator == null ? "" : normalizedCreator);
        model.addAttribute("searchSort", normalizedSort);
        model.addAttribute("searchTagMode", normalizedTagMode);
        model.addAttribute("selectedTagSlugs", tagSlugs);
        model.addAttribute("availableTags", availableTags);
        model.addAttribute("searchQuery", "");

        return "index";
    }

    private List<String> parseTagSlugs(String tagsCsv) {
        Set<String> slugs = new LinkedHashSet<>();
        if (tagsCsv != null) {
            for (String token : tagsCsv.split(",")) {
                String slug = TagSanitizer.toSlug(token);
                if (TagSanitizer.isAllowed(slug)) {
                    slugs.add(slug);
                }
            }
        }
        return new ArrayList<>(slugs);
    }

    private String trimToNull(String value) {
        if (value == null) {
            return null;
        }
        String text = value.trim();
        return text.isBlank() ? null : text;
    }
}
