package com.eactive.testmaster.client.service;

import com.eactive.testmaster.client.dto.ApiRequestDTO;
import com.eactive.testmaster.client.dto.ApiRequestKeyValueDTO;
import io.netty.util.CharsetUtil;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;

public class RequestCharsetUtils {
    private static final Pattern CHARSET_PATTERN = Pattern.compile("charset\\s*=\\s*([^;\\s]+)", Pattern.CASE_INSENSITIVE);
    private static final String CONTENT_TYPE_HEADER = "Content-Type";
    private static final Charset DEFAULT_CHARSET = determineDefaultCharset();

    /**
     * Determines the default charset based on system properties
     * Falls back to UTF-8 if system encoding is not available or invalid
     */
    private static Charset determineDefaultCharset() {
        try {
            String systemEncoding = System.getProperty("file.encoding");
            if (StringUtils.isNotBlank(systemEncoding)) {
                return Charset.forName(systemEncoding);
            }
        } catch (IllegalArgumentException | SecurityException e) {
            // Log warning about fallback to UTF-8
        }
        return CharsetUtil.UTF_8;
    }

    /**
     * Extracts charset from request headers with fallback to system default charset
     * @param apiRequest The API request containing headers
     * @return The detected charset or system default charset
     */
    public static Charset extractRequestCharset(ApiRequestDTO apiRequest) {
        if (apiRequest == null || apiRequest.getHeaders() == null) {
            return DEFAULT_CHARSET;
        }

        return apiRequest.getHeaders().stream()
            .filter(ApiRequestKeyValueDTO::isEnabled)
            .filter(header -> CONTENT_TYPE_HEADER.equalsIgnoreCase(header.getKey()))
            .findFirst()
            .map(RequestCharsetUtils::parseCharsetFromContentType)
            .orElse(DEFAULT_CHARSET);
    }

    /**
     * Parses charset from Content-Type header value
     * @param contentTypeHeader The Content-Type header DTO
     * @return The detected charset or system default charset
     */
    private static Charset parseCharsetFromContentType(ApiRequestKeyValueDTO contentTypeHeader) {
        String contentType = contentTypeHeader.getValue();
        if (StringUtils.isBlank(contentType)) {
            return DEFAULT_CHARSET;
        }

        Matcher matcher = CHARSET_PATTERN.matcher(contentType);
        if (matcher.find()) {
            String charsetName = matcher.group(1).trim();
            try {
                return Charset.forName(charsetName);
            } catch (IllegalArgumentException e) {
                // Log warning about unsupported charset
                return DEFAULT_CHARSET;
            }
        }

        // Handle common content types without explicit charset
        if (contentType.contains("application/json")) {
            return CharsetUtil.UTF_8; // JSON should always use UTF-8 per RFC 8259
        }

        return DEFAULT_CHARSET;
    }

}
