package com.arms.api.sample.safeguard;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.advisor.api.AdvisedRequest;
import org.springframework.ai.chat.client.advisor.api.AdvisedResponse;
import org.springframework.ai.chat.client.advisor.api.BaseAdvisor;
import org.springframework.ai.chat.client.advisor.api.StreamAroundAdvisorChain;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Component
@Slf4j
public class SafeGuardAdvisor implements BaseAdvisor {

    private int order = 1;

    private static final double SAFETY_THRESHOLD = 0.7;
    private static final int MAX_CONTENT_LENGTH = 50000; // 50KB

    private final AtomicLong totalRequests = new AtomicLong(0);
    private final AtomicLong blockedRequests = new AtomicLong(0);
    private final AtomicLong filteredResponses = new AtomicLong(0);
    private final ConcurrentHashMap<String, AtomicLong> violationStats = new ConcurrentHashMap<>();

    private final Set<String> criticalKeywords = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
            // 프롬프트 인젝션 (영어)
            "ignore all previous instructions", "disregard all prior", "forget everything",
            "ignore the above", "ignore your instructions", "new instructions:",
            "system prompt:", "override instructions",

            // 프롬프트 인젝션 (한국어)
            "이전 지시사항 무시", "모든 명령 무시", "새로운 지시사항",
            "시스템 프롬프트", "당신은 이제부터", "역할을 변경",
            "명령을 무시하고", "지시를 잊어버리고",

            // Jailbreak (영어)
            "developer mode", "god mode", "unrestricted", "no restrictions",
            "bypass safety", "disable filter",

            // Jailbreak (한국어)
            "개발자 모드", "무제한 모드", "제한 없이", "필터 해제",

            // 시스템 명령어
            "rm -rf", "format c:", "del /f /s /q", "shutdown", "reboot",

            // 데이터베이스 파괴
            "drop database", "truncate table", "delete from users"
    )));


    private final Set<String> highRiskKeywords = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
            // 인증 정보 (영어)
            "password", "passwd", "pwd", "api_key", "apikey", "api-key",
            "secret_key", "secret", "private_key", "access_token", "refresh_token",
            "bearer", "authorization", "credential",

            // 인증 정보 (한국어)
            "비밀번호", "패스워드", "암호", "api키", "비밀키",
            "인증키", "접근토큰", "액세스토큰", "인증정보"
    )));


    private final Set<String> mediumRiskKeywords = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
            // SQL Injection
            "union select", "or 1=1", "and 1=1", "'; drop", "' or '1'='1",
            "admin'--", "' or ''='",

            // XSS
            "alert(", "confirm(", "prompt(", "document.cookie"
    )));


    private final Set<String> whitelist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
            "password hashing", "password encryption", "password security",
            "how to secure password", "password best practices",
            "비밀번호 암호화", "비밀번호 보안", "비밀번호 해싱",
            "sql injection prevention", "xss prevention", "security best practices",
            "sql 인젝션 방어", "xss 방어", "보안 모범 사례"
    )));


    private final Map<String, Pattern> compiledPatterns = new HashMap<>();

    public SafeGuardAdvisor() {
        initializePatterns();
    }


    private void initializePatterns() {
        // SQL Injection
        compiledPatterns.put("SQL_UNION", Pattern.compile(
                "(?i)\\b(union|select|insert|update|delete|drop)\\s+(all\\s+)?(select|from|into|table|where)",
                Pattern.CASE_INSENSITIVE
        ));

        compiledPatterns.put("SQL_COMMENT", Pattern.compile(
                "--[^\n]*|/\\*.*?\\*/|#[^\n]*",
                Pattern.CASE_INSENSITIVE
        ));

        // XSS
        compiledPatterns.put("XSS_SCRIPT", Pattern.compile(
                "<script[^>]*>.*?</script>|<iframe[^>]*>.*?</iframe>",
                Pattern.CASE_INSENSITIVE | Pattern.DOTALL
        ));

        compiledPatterns.put("XSS_EVENT", Pattern.compile(
                "on(load|error|click|mouse\\w+|key\\w+)\\s*=",
                Pattern.CASE_INSENSITIVE
        ));

        compiledPatterns.put("XSS_JAVASCRIPT", Pattern.compile(
                "javascript:\\s*",
                Pattern.CASE_INSENSITIVE
        ));

        // 파일 경로 탐색
        compiledPatterns.put("PATH_TRAVERSAL", Pattern.compile(
                "(\\.\\./|\\.\\\\|%2e%2e%2f|%2e%2e/|\\.\\.%2f)",
                Pattern.CASE_INSENSITIVE
        ));

        // 명령어 삽입
        compiledPatterns.put("COMMAND_INJECTION", Pattern.compile(
                "\\b(exec|system|eval|cmd|sh|bash|powershell|shell_exec)\\s*[\\(\\[]",
                Pattern.CASE_INSENSITIVE
        ));

        // 프롬프트 인젝션 패턴 (OWASP LLM01:2025)
        compiledPatterns.put("PROMPT_INJECTION", Pattern.compile(
                "(?i)(ignore|disregard|forget|bypass|override)\\s+(all|previous|prior|above|your)\\s+(instructions?|commands?|rules?|prompts?)",
                Pattern.CASE_INSENSITIVE
        ));

        // 역할 조작
        compiledPatterns.put("ROLE_MANIPULATION", Pattern.compile(
                "(?i)(you\\s+are\\s+now|act\\s+as|pretend\\s+to\\s+be|roleplay\\s+as|assume\\s+the\\s+role)",
                Pattern.CASE_INSENSITIVE
        ));

        // 민감 정보 패턴들
        compiledPatterns.put("EMAIL", Pattern.compile(
                "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
        ));

        compiledPatterns.put("PHONE_KR", Pattern.compile(
                "0\\d{1,2}-\\d{3,4}-\\d{4}|01[016789]-\\d{3,4}-\\d{4}"
        ));

        compiledPatterns.put("CREDIT_CARD", Pattern.compile(
                "\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}"
        ));

        // 주민등록번호 (한국)
        compiledPatterns.put("SSN_KR", Pattern.compile(
                "\\d{6}[-\\s]?[1-4]\\d{6}"
        ));

        // JWT 토큰
        compiledPatterns.put("JWT_TOKEN", Pattern.compile(
                "eyJ[a-zA-Z0-9_-]+\\.eyJ[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+"
        ));

        // Base64 인코딩된 긴 문자열 (잠재적 비밀키)
        compiledPatterns.put("BASE64_LONG", Pattern.compile(
                "(?:[A-Za-z0-9+/]{4}){20,}(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?"
        ));
    }

    @Override
    public AdvisedRequest before(AdvisedRequest request) {
        totalRequests.incrementAndGet();
        long startTime = System.currentTimeMillis();

        log.info("SafeGuardAdvisor::before - Request #{} 보안 검증 시작", totalRequests.get());

        String userText = request.userText();

        // 빈 요청 처리
        if (userText == null || userText.trim().isEmpty()) {
            log.debug("SafeGuardAdvisor::before - 빈 요청, 패스");
            return request;
        }

        // 1. 화이트리스트 검사 (먼저 검사하여 성능 최적화)
        if (isWhitelisted(userText)) {
            log.info("SafeGuardAdvisor::before - 화이트리스트 매칭, 검증 패스");
            return request;
        }

        // 2. 입력 검증
        ValidationResult inputValidation = validateContent(userText, "REQUEST");

        long processingTime = System.currentTimeMillis() - startTime;
        log.info("SafeGuardAdvisor::before - 검증 완료 ({}ms), 안전: {}",
                processingTime, inputValidation.isSafe());

        if (!inputValidation.isSafe()) {
            blockedRequests.incrementAndGet();

            // 통계 업데이트
            for (String violation : inputValidation.getViolations()) {
                violationStats.computeIfAbsent(violation, k -> new AtomicLong(0)).incrementAndGet();
            }

            // 심각도에 따른 로그 레벨 조정
            if (inputValidation.getSeverity() == Severity.CRITICAL) {
                log.error("SafeGuardAdvisor::before - CRITICAL 위협 탐지! Violations: {}, Details: {}",
                        inputValidation.getViolations(),
                        inputValidation.getAllViolationDetails());
            } else {
                log.warn("SafeGuardAdvisor::before - {} 위협 탐지, Violations: {}",
                        inputValidation.getSeverity(),
                        inputValidation.getViolations());
            }

            // 위험한 요청은 안전한 메시지로 대체
            return AdvisedRequest.from(request)
                    .userText(getSafeAlternativeMessage(inputValidation))
                    .userParams(addSafetyMetadata(request.userParams(), inputValidation))
                    .build();
        }

        // 3. 컨텍스트 파라미터 검증 및 살균
        Map<String, Object> sanitizedParams = sanitizeParameters(request.userParams());

        return AdvisedRequest.from(request)
                .userParams(sanitizedParams)
                .build();
    }

    @Override
    public AdvisedResponse after(AdvisedResponse response) {
        log.info("SafeGuardAdvisor::after - 응답 필터링 시작");

        // ChatResponse에서 실제 텍스트 추출
        String responseText = extractTextFromResponse(response);

        if (responseText == null || responseText.trim().isEmpty()) {
            return response;
        }

        // 1. 응답 콘텐츠 검증
        ValidationResult responseValidation = validateContent(responseText, "RESPONSE");

        String processedResponse = responseText;
        boolean wasFiltered = false;

        if (!responseValidation.isSafe()) {
            filteredResponses.incrementAndGet();

            log.warn("SafeGuardAdvisor::after - 응답에서 {} 위협 탐지: {}",
                    responseValidation.getSeverity(),
                    responseValidation.getViolations());

            // 심각도에 따른 처리
            if (responseValidation.getSeverity() == Severity.CRITICAL) {
                // CRITICAL: 응답 전체 차단
                processedResponse = "보안 정책에 따라 해당 응답을 제공할 수 없습니다. (위험 등급: 높음)";
                wasFiltered = true;
            } else {
                // 부분 필터링
                processedResponse = filterResponse(responseText, responseValidation);
                wasFiltered = !processedResponse.equals(responseText);
            }
        }

        // 2. 민감 정보 마스킹
        String maskedResponse = maskSensitiveData(processedResponse);
        if (!maskedResponse.equals(processedResponse)) {
            wasFiltered = true;
            log.info("SafeGuardAdvisor::after - 민감 정보 마스킹 적용");
        }

        // 3. 안전성 점수 계산
        double safetyScore = calculateSafetyScore(responseText);

        // 4. 응답에 안전성 메타데이터 추가
        Map<String, Object> adviseContext = new HashMap<>(response.adviseContext());
        adviseContext.put("safeguard_checked", true);
        adviseContext.put("safeguard_version", "2.0");
        adviseContext.put("safety_score", safetyScore);
        adviseContext.put("filtered", wasFiltered);
        adviseContext.put("severity", responseValidation.getSeverity().name());
        adviseContext.put("timestamp", LocalDateTime.now().toString());

        if (wasFiltered) {
            adviseContext.put("filter_reason", responseValidation.getViolations());
        }

        log.info("SafeGuardAdvisor::after - 처리 완료 (Score: {}, Filtered: {})",
                safetyScore, wasFiltered);

        // ChatResponse의 메타데이터도 추가
        Map<String, Object> chatResponseMetadata = new HashMap<>();
        chatResponseMetadata.put("safeguard_checked", true);
        chatResponseMetadata.put("safety_score", safetyScore);

        // 수정된 텍스트로 ChatResponse 재생성
        var modifiedChatResponse = createChatResponse(maskedResponse, chatResponseMetadata);

        return AdvisedResponse.from(response)
                .response(modifiedChatResponse)
                .adviseContext(adviseContext)
                .build();
    }

    @Override
    public Flux<AdvisedResponse> aroundStream(AdvisedRequest request, StreamAroundAdvisorChain chain) {
        log.info("SafeGuardAdvisor::aroundStream - 스트림 모니터링 시작");

        final AtomicLong chunkCount = new AtomicLong(0);
        final AtomicLong filteredChunkCount = new AtomicLong(0);

        // 스트림 응답도 실시간으로 필터링
        return chain.nextAroundStream(request)
                .map(response -> {
                    long currentChunk = chunkCount.incrementAndGet();

                    // ChatResponse에서 실제 텍스트 추출
                    String content = extractTextFromResponse(response);

                    if (content == null || content.isEmpty()) {
                        return response;
                    }

                    // 각 청크 검증
                    ValidationResult validation = validateContentStream(content);

                    if (!validation.isSafe()) {
                        filteredChunkCount.incrementAndGet();

                        log.debug("SafeGuardAdvisor::aroundStream - Chunk #{} 필터링 ({})",
                                currentChunk, validation.getViolations());

                        String filteredContent;
                        if (validation.getSeverity() == Severity.CRITICAL) {
                            filteredContent = "[BLOCKED]";
                        } else {
                            filteredContent = filterResponse(content, validation);
                        }

                        // 민감 정보 마스킹
                        filteredContent = maskSensitiveData(filteredContent);

                        // 수정된 텍스트로 ChatResponse 재생성
                        return AdvisedResponse.from(response)
                                .response(createChatResponse(filteredContent, null))
                                .build();
                    }

                    // 민감 정보 마스킹만 적용
                    String maskedContent = maskSensitiveData(content);
                    if (!maskedContent.equals(content)) {
                        // 수정된 텍스트로 ChatResponse 재생성
                        return AdvisedResponse.from(response)
                                .response(createChatResponse(maskedContent, null))
                                .build();
                    }

                    return response;
                })
                .doOnComplete(() -> {
                    log.info("SafeGuardAdvisor::aroundStream - 스트림 완료 " +
                                    "(총 청크: {}, 필터링된 청크: {})",
                            chunkCount.get(), filteredChunkCount.get());
                })
                .doOnError(error -> {
                    log.error("SafeGuardAdvisor::aroundStream - 스트림 에러", error);
                });
    }

    // ========== 유틸리티 메서드 ==========

    /**
     * AdvisedResponse에서 텍스트 추출
     */
    private String extractTextFromResponse(AdvisedResponse response) {
        if (response.response() == null
                || response.response().getResult() == null
                || response.response().getResult().getOutput() == null) {
            return null;
        }
        // AssistantMessage.getText() 사용
        return response.response().getResult().getOutput().getText();
    }

    /**
     * 텍스트로 ChatResponse 생성
     */
    private ChatResponse createChatResponse(String text, Map<String, Object> metadata) {
        // AssistantMessage 생성
        var assistantMessage = new AssistantMessage(text);

        // Generation 생성
        var generation = new Generation(assistantMessage);

        // ChatResponse 생성 (생성자 직접 사용)
        return new ChatResponse(List.of(generation));
    }

    // ========== 검증 로직 ==========

    /**
     * 콘텐츠 검증 (전체)
     */
    private ValidationResult validateContent(String content, String type) {
        ValidationResult result = new ValidationResult();

        if (content == null || content.trim().isEmpty()) {
            return result;
        }

        String lowerContent = content.toLowerCase();

        // 1. 콘텐츠 길이 검사
        if (content.length() > MAX_CONTENT_LENGTH) {
            result.addViolation("CONTENT_TOO_LONG",
                    String.format("Length: %d (max: %d)", content.length(), MAX_CONTENT_LENGTH),
                    Severity.HIGH);
        }

        // 2. CRITICAL 키워드 검사
        for (String keyword : criticalKeywords) {
            if (lowerContent.contains(keyword.toLowerCase())) {
                result.addViolation("CRITICAL_KEYWORD", keyword, Severity.CRITICAL);
            }
        }

        // 3. HIGH 위험 키워드 검사
        for (String keyword : highRiskKeywords) {
            if (lowerContent.contains(keyword.toLowerCase())) {
                result.addViolation("HIGH_RISK_KEYWORD", keyword, Severity.HIGH);
            }
        }

        // 4. MEDIUM 위험 키워드 검사
        for (String keyword : mediumRiskKeywords) {
            if (lowerContent.contains(keyword.toLowerCase())) {
                result.addViolation("MEDIUM_RISK_KEYWORD", keyword, Severity.MEDIUM);
            }
        }

        // 5. 정규식 패턴 검사
        checkPattern(content, "SQL_UNION", result, Severity.HIGH);
        checkPattern(content, "SQL_COMMENT", result, Severity.MEDIUM);
        checkPattern(content, "XSS_SCRIPT", result, Severity.CRITICAL);
        checkPattern(content, "XSS_EVENT", result, Severity.HIGH);
        checkPattern(content, "XSS_JAVASCRIPT", result, Severity.HIGH);
        checkPattern(content, "PATH_TRAVERSAL", result, Severity.HIGH);
        checkPattern(content, "COMMAND_INJECTION", result, Severity.CRITICAL);
        checkPattern(content, "PROMPT_INJECTION", result, Severity.CRITICAL);
        checkPattern(content, "ROLE_MANIPULATION", result, Severity.HIGH);

        return result;
    }

    /**
     * 스트림용 경량 검증 (성능 최적화)
     */
    private ValidationResult validateContentStream(String content) {
        ValidationResult result = new ValidationResult();

        if (content == null || content.trim().isEmpty()) {
            return result;
        }

        String lowerContent = content.toLowerCase();

        // CRITICAL 키워드만 검사 (성능 최적화)
        for (String keyword : criticalKeywords) {
            if (lowerContent.contains(keyword.toLowerCase())) {
                result.addViolation("CRITICAL_KEYWORD", keyword, Severity.CRITICAL);
            }
        }

        // 주요 패턴만 검사
        checkPattern(content, "XSS_SCRIPT", result, Severity.CRITICAL);
        checkPattern(content, "COMMAND_INJECTION", result, Severity.CRITICAL);
        checkPattern(content, "PROMPT_INJECTION", result, Severity.CRITICAL);

        return result;
    }

    /**
     * 패턴 검사 헬퍼 메서드
     */
    private void checkPattern(String content, String patternKey, ValidationResult result, Severity severity) {
        Pattern pattern = compiledPatterns.get(patternKey);
        if (pattern != null && pattern.matcher(content).find()) {
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                String matched = matcher.group();
                result.addViolation(patternKey,
                        matched.length() > 50 ? matched.substring(0, 50) + "..." : matched,
                        severity);
            }
        }
    }

    /**
     * 화이트리스트 검사
     */
    private boolean isWhitelisted(String content) {
        String lowerContent = content.toLowerCase();
        return whitelist.stream()
                .anyMatch(whitelistItem -> lowerContent.contains(whitelistItem.toLowerCase()));
    }

    // ========== 필터링 및 살균 ==========

    /**
     * 파라미터 살균 처리
     */
    private Map<String, Object> sanitizeParameters(Map<String, Object> params) {
        Map<String, Object> sanitized = new HashMap<>();

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            // 키 검증
            if (isValidParameterKey(key)) {
                // 값 살균
                if (value instanceof String) {
                    sanitized.put(key, sanitizeString((String) value));
                } else if (value instanceof List) {
                    sanitized.put(key, sanitizeList((List<?>) value));
                } else if (value instanceof Map) {
                    sanitized.put(key, sanitizeParameters((Map<String, Object>) value));
                } else {
                    sanitized.put(key, value);
                }
            } else {
                log.warn("SafeGuardAdvisor - 유효하지 않은 파라미터 키 제거: {}", key);
            }
        }

        return sanitized;
    }

    /**
     * 리스트 살균
     */
    private List<?> sanitizeList(List<?> list) {
        return list.stream()
                .map(item -> {
                    if (item instanceof String) {
                        return sanitizeString((String) item);
                    } else if (item instanceof Map) {
                        return sanitizeParameters((Map<String, Object>) item);
                    }
                    return item;
                })
                .collect(Collectors.toList());
    }

    /**
     * 문자열 살균 처리
     */
    private String sanitizeString(String input) {
        if (input == null) return null;

        String sanitized = input;

        // HTML 태그 제거
        sanitized = sanitized.replaceAll("<[^>]*>", "");

        // 스크립트 관련 문자열 제거
        sanitized = sanitized.replaceAll("(?i)javascript:", "");
        sanitized = sanitized.replaceAll("(?i)on\\w+\\s*=", "");

        // SQL 주석 제거
        sanitized = sanitized.replaceAll("--[^\n]*", "");
        sanitized = sanitized.replaceAll("/\\*.*?\\*/", "");

        // 다중 공백 정리
        sanitized = sanitized.replaceAll("\\s+", " ").trim();

        return sanitized;
    }

    /**
     * 민감 데이터 마스킹
     */
    private String maskSensitiveData(String content) {
        if (content == null) return null;

        String masked = content;

        // 이메일 마스킹
        Pattern emailPattern = compiledPatterns.get("EMAIL");
        if (emailPattern != null) {
            masked = emailPattern.matcher(masked).replaceAll(matchResult -> {
                String email = matchResult.group();
                String[] parts = email.split("@");
                if (parts.length == 2) {
                    String username = parts[0];
                    String domain = parts[1];
                    String maskedUsername = username.length() > 2
                            ? username.substring(0, 2) + "***"
                            : "***";
                    return maskedUsername + "@" + domain;
                }
                return "***@***.***";
            });
        }

        // 전화번호 마스킹 (한국)
        masked = compiledPatterns.get("PHONE_KR").matcher(masked)
                .replaceAll("***-****-****");

        // 신용카드 번호 마스킹
        masked = compiledPatterns.get("CREDIT_CARD").matcher(masked)
                .replaceAll("****-****-****-****");

        // 주민등록번호 마스킹
        masked = compiledPatterns.get("SSN_KR").matcher(masked)
                .replaceAll(matchResult -> {
                    String ssn = matchResult.group();
                    return ssn.substring(0, 6) + "-*******";
                });

        // JWT 토큰 마스킹
        masked = compiledPatterns.get("JWT_TOKEN").matcher(masked)
                .replaceAll("[JWT_TOKEN_MASKED]");

        // 긴 Base64 문자열 마스킹
        masked = compiledPatterns.get("BASE64_LONG").matcher(masked)
                .replaceAll("[ENCODED_DATA_MASKED]");

        return masked;
    }

    /**
     * 안전한 대체 메시지 생성
     */
    private String getSafeAlternativeMessage(ValidationResult validation) {
        Severity severity = validation.getSeverity();

        switch (severity) {
            case CRITICAL:
                return "죄송합니다. 요청하신 내용에 심각한 보안 위험 요소가 포함되어 있어 처리할 수 없습니다. " +
                        "시스템 관리자에게 문의해 주시기 바랍니다.";
            case HIGH:
                return "죄송합니다. 요청하신 내용에 보안상 위험한 요소가 포함되어 있어 처리할 수 없습니다. " +
                        "다른 방식으로 질문해 주시기 바랍니다.";
            case MEDIUM:
                return "죄송합니다. 요청하신 내용에 부적절한 요소가 포함되어 있을 수 있습니다. " +
                        "질문을 다시 작성해 주시기 바랍니다.";
            default:
                return "죄송합니다. 요청을 처리할 수 없습니다. 질문을 다시 작성해 주시기 바랍니다.";
        }
    }

    /**
     * 응답 필터링
     */
    private String filterResponse(String response, ValidationResult validation) {
        if (validation.getSeverity() == Severity.CRITICAL) {
            return "보안 정책에 따라 해당 응답을 제공할 수 없습니다. (위험 등급: 높음)";
        }

        String filtered = response;

        // 위반 항목별 필터링
        Map<Severity, List<String>> violationsBySeverity = validation.getViolationsBySeverity();

        // HIGH/MEDIUM 위반: 해당 부분만 마스킹
        for (Severity severity : Arrays.asList(Severity.HIGH, Severity.MEDIUM)) {
            if (violationsBySeverity.containsKey(severity)) {
                for (String detail : validation.getViolationDetailsBySeverity(severity)) {
                    String escapedDetail = Pattern.quote(detail);
                    filtered = filtered.replaceAll("(?i)" + escapedDetail, "[FILTERED]");
                }
            }
        }

        return filtered;
    }

    // ========== 점수 및 통계 ==========

    /**
     * 안전성 점수 계산
     */
    private double calculateSafetyScore(String content) {
        if (content == null || content.isEmpty()) return 1.0;

        double score = 1.0;
        ValidationResult validation = validateContent(content, "SCORE");

        // 심각도별 감점
        Map<Severity, List<String>> violationsBySeverity = validation.getViolationsBySeverity();

        score -= violationsBySeverity.getOrDefault(Severity.CRITICAL, Collections.emptyList()).size() * 0.5;
        score -= violationsBySeverity.getOrDefault(Severity.HIGH, Collections.emptyList()).size() * 0.3;
        score -= violationsBySeverity.getOrDefault(Severity.MEDIUM, Collections.emptyList()).size() * 0.15;

        return Math.max(0, Math.min(1, score));
    }

    /**
     * 파라미터 키 유효성 검사
     */
    private boolean isValidParameterKey(String key) {
        // 알파벳, 숫자, 언더스코어, 하이픈만 허용
        return key != null && key.matches("^[a-zA-Z0-9_-]+$");
    }

    /**
     * 안전성 메타데이터 추가
     */
    private Map<String, Object> addSafetyMetadata(Map<String, Object> params, ValidationResult validation) {
        Map<String, Object> enriched = new HashMap<>(params);
        enriched.put("safeguard_filtered", true);
        enriched.put("safeguard_violations", validation.getViolations());
        enriched.put("safeguard_severity", validation.getSeverity().name());
        enriched.put("safeguard_timestamp", LocalDateTime.now().toString());
        return enriched;
    }

    /**
     * 보안 통계 조회
     */
    public SafeGuardStats getStats() {
        return new SafeGuardStats(
                totalRequests.get(),
                blockedRequests.get(),
                filteredResponses.get(),
                new HashMap<>(violationStats.entrySet().stream()
                        .collect(Collectors.toMap(
                                Map.Entry::getKey,
                                e -> e.getValue().get()
                        )))
        );
    }

    /**
     * 통계 초기화
     */
    public void resetStats() {
        totalRequests.set(0);
        blockedRequests.set(0);
        filteredResponses.set(0);
        violationStats.clear();
        log.info("SafeGuardAdvisor - 통계 초기화 완료");
    }

    // ========== Getter/Setter ==========

    @Override
    public int getOrder() {
        return this.order;
    }

    public SafeGuardAdvisor withOrder(int order) {
        this.order = order;
        return this;
    }

    // ========== 내부 클래스 ==========

    /**
     * 심각도 레벨
     */
    public enum Severity {
        LOW(1),
        MEDIUM(2),
        HIGH(3),
        CRITICAL(4);

        private final int level;

        Severity(int level) {
            this.level = level;
        }

        public int getLevel() {
            return level;
        }
    }

    /**
     * 검증 결과 클래스
     */
    @Getter
    public static class ValidationResult {
        private final Map<String, List<ViolationDetail>> violations = new HashMap<>();
        private Severity maxSeverity = Severity.LOW;

        public void addViolation(String type, String detail, Severity severity) {
            violations.computeIfAbsent(type, k -> new ArrayList<>())
                    .add(new ViolationDetail(detail, severity));

            // 최대 심각도 업데이트
            if (severity.getLevel() > maxSeverity.getLevel()) {
                maxSeverity = severity;
            }
        }

        public boolean isSafe() {
            return violations.isEmpty();
        }

        public Set<String> getViolations() {
            return violations.keySet();
        }

        public List<String> getViolationDetails(String type) {
            return violations.getOrDefault(type, Collections.emptyList()).stream()
                    .map(ViolationDetail::getDetail)
                    .collect(Collectors.toList());
        }

        public Map<String, List<String>> getAllViolationDetails() {
            return violations.entrySet().stream()
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            e -> e.getValue().stream()
                                    .map(ViolationDetail::getDetail)
                                    .collect(Collectors.toList())
                    ));
        }

        public boolean hasViolation(String type) {
            return violations.containsKey(type);
        }

        public Severity getSeverity() {
            return maxSeverity;
        }

        public Map<Severity, List<String>> getViolationsBySeverity() {
            Map<Severity, List<String>> result = new HashMap<>();

            for (Map.Entry<String, List<ViolationDetail>> entry : violations.entrySet()) {
                for (ViolationDetail detail : entry.getValue()) {
                    result.computeIfAbsent(detail.getSeverity(), k -> new ArrayList<>())
                            .add(detail.getDetail());
                }
            }

            return result;
        }

        public List<String> getViolationDetailsBySeverity(Severity severity) {
            return violations.values().stream()
                    .flatMap(List::stream)
                    .filter(detail -> detail.getSeverity() == severity)
                    .map(ViolationDetail::getDetail)
                    .collect(Collectors.toList());
        }

        @Getter
        private static class ViolationDetail {
            private final String detail;
            private final Severity severity;

            public ViolationDetail(String detail, Severity severity) {
                this.detail = detail;
                this.severity = severity;
            }
        }
    }

    /**
     * 통계 정보 클래스
     */
    @Getter
    public static class SafeGuardStats {
        private final long totalRequests;
        private final long blockedRequests;
        private final long filteredResponses;
        private final Map<String, Long> violationStats;
        private final double blockRate;

        public SafeGuardStats(long totalRequests, long blockedRequests,
                              long filteredResponses, Map<String, Long> violationStats) {
            this.totalRequests = totalRequests;
            this.blockedRequests = blockedRequests;
            this.filteredResponses = filteredResponses;
            this.violationStats = violationStats;
            this.blockRate = totalRequests > 0
                    ? (double) blockedRequests / totalRequests * 100
                    : 0.0;
        }

        @Override
        public String toString() {
            return String.format(
                    "SafeGuardStats{총요청=%d, 차단=%d, 필터링=%d, 차단율=%.2f%%, 위반통계=%s}",
                    totalRequests, blockedRequests, filteredResponses, blockRate, violationStats
            );
        }
    }
}