package com.pandoli365.bibimbap.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

public final class TagSanitizer {

    // 화이트리스트: 한글(가-힣, ㄱ-ㅎ, ㅏ-ㅣ) + 영소문자 + 숫자 + 하이픈.
    // <,>,",',(,),/ 등 특수문자를 전부 배제하므로 <script> 등 XSS 페이로드는 toSlug 단계에서 무력화된다.
    private static final String ALLOWED_CHAR_CLASS = "a-z0-9가-힣ㄱ-ㅎㅏ-ㅣ-";

    private static final int MIN_LENGTH = 2;
    private static final int MAX_LENGTH = 20;

    private static final Set<String> BANNED_WORDS = loadBannedWords();

    private TagSanitizer() {
    }

    // 앱 기동을 막지 않기 위해 로드 실패 시 예외 대신 빈 Set 으로 폴백한다.
    private static Set<String> loadBannedWords() {
        Set<String> words = new HashSet<>();
        try (InputStream in = TagSanitizer.class.getResourceAsStream("/banned-words.txt")) {
            if (in == null) {
                return Collections.emptySet();
            }
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    String word = line.trim().toLowerCase(Locale.ROOT);
                    if (word.isEmpty() || word.startsWith("#")) {
                        continue;
                    }
                    words.add(word);
                }
            }
        } catch (Exception e) {
            return Collections.emptySet();
        }
        return Collections.unmodifiableSet(words);
    }

    // trim·소문자·정규화. 한/영/숫자 보존, 공백→하이픈, 그 외 제거, 연속 하이픈 축약, 양끝 하이픈 제거. null→"".
    public static String toSlug(String rawName) {
        if (rawName == null) {
            return "";
        }
        String s = rawName.trim().toLowerCase(Locale.ROOT);
        s = s.replaceAll("\\s+", "-");
        s = s.replaceAll("[^" + ALLOWED_CHAR_CLASS + "]", "");
        s = s.replaceAll("-{2,}", "-");
        s = s.replaceAll("^-+", "").replaceAll("-+$", "");
        return s;
    }

    // 길이 2~20(slug 기준) + 화이트리스트(한글/영문/숫자/하이픈) + 금칙어 미매치 통합 판정.
    // 입력은 toSlug 를 통과한 slug 라고 가정하되, 화이트리스트를 재검증하여 한 번 더 방어한다.
    public static boolean isAllowed(String slug) {
        if (slug == null || slug.isBlank()) {
            return false;
        }
        int len = slug.length();
        if (len < MIN_LENGTH || len > MAX_LENGTH) {
            return false;
        }
        if (!slug.matches("[" + ALLOWED_CHAR_CLASS + "]+")) {
            return false;
        }
        for (String banned : BANNED_WORDS) {
            if (banned.isEmpty()) {
                continue;
            }
            if (slug.contains(banned) || banned.contains(slug)) {
                return false;
            }
        }
        return true;
    }
}
