package ru.shine.promo.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import ru.shine.promo.config.AppProperties;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Pattern;

@Service
public class PromoCodeService {

    private static final Logger log = LoggerFactory.getLogger(PromoCodeService.class);
    private static final Pattern PROMO_CODE_PATTERN = Pattern.compile("^[a-z0-9]{8}$");

    private final AppProperties appProperties;

    public PromoCodeService(AppProperties appProperties) {
        this.appProperties = appProperties;
    }

    public String normalizePromoCode(String rawPromoCode) {
        if (rawPromoCode == null) {
            return "";
        }
        return rawPromoCode.trim().toLowerCase();
    }

    public boolean isPromoCodeFormatValid(String promoCode) {
        return PROMO_CODE_PATTERN.matcher(promoCode).matches();
    }

    public boolean isEternalPromoCode(String promoCode) {
        if (!appProperties.isPromoEternalCodeEnabled()) {
            return false;
        }
        String configured = appProperties.getPromoEternalCodeValue();
        return !configured.isEmpty() && configured.equals(promoCode);
    }

    public boolean promoCodeExists(String promoCode) {
        Set<String> codes = readPromoCodesFromFile();
        return codes.contains(promoCode);
    }

    private Set<String> readPromoCodesFromFile() {
        Path file = Path.of(appProperties.getPromoCodesFile());
        if (!Files.exists(file)) {
            throw new PromoException(HttpStatus.INTERNAL_SERVER_ERROR, "Ошибка чтения файла промокодов");
        }

        try {
            Set<String> result = new LinkedHashSet<>();
            for (String row : Files.readAllLines(file, StandardCharsets.UTF_8)) {
                String line = row.trim().toLowerCase();
                if (line.isEmpty() || line.startsWith("#")) {
                    continue;
                }
                if (!isPromoCodeFormatValid(line)) {
                    log.warn("Skipped invalid promo code row in {}: {}", file, line);
                    continue;
                }
                result.add(line);
            }
            return result;
        } catch (IOException e) {
            throw new PromoException(HttpStatus.INTERNAL_SERVER_ERROR, "Ошибка чтения файла промокодов", e);
        }
    }
}
