package research.loghunter.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import research.loghunter.dto.PatternDto;
import research.loghunter.entity.Pattern;
import research.loghunter.repository.PatternRepository;

import java.util.List;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class PatternService {

    private final PatternRepository patternRepository;

    public List<PatternDto> findAll() {
        return patternRepository.findAll().stream()
                .map(this::toDto)
                .collect(Collectors.toList());
    }

    public List<PatternDto> findAllActive() {
        return patternRepository.findByActiveTrueOrderBySeverityAscNameAsc().stream()
                .map(this::toDto)
                .collect(Collectors.toList());
    }

    public PatternDto findById(Long id) {
        return patternRepository.findById(id)
                .map(this::toDto)
                .orElseThrow(() -> new RuntimeException("Pattern not found: " + id));
    }

    @Transactional
    public PatternDto create(PatternDto dto) {
        validateRegex(dto.getRegex());
        if (dto.getExcludeRegex() != null && !dto.getExcludeRegex().isBlank()) {
            validateRegex(dto.getExcludeRegex());
        }
        
        Pattern pattern = Pattern.builder()
                .name(dto.getName())
                .regex(dto.getRegex())
                .excludeRegex(dto.getExcludeRegex())
                .severity(dto.getSeverity() != null ? dto.getSeverity() : "ERROR")
                .contextLines(dto.getContextLines() != null ? dto.getContextLines() : 5)
                .description(dto.getDescription())
                .active(dto.getActive() != null ? dto.getActive() : true)
                .build();

        pattern = patternRepository.save(pattern);
        return toDto(pattern);
    }

    @Transactional
    public PatternDto update(Long id, PatternDto dto) {
        validateRegex(dto.getRegex());
        if (dto.getExcludeRegex() != null && !dto.getExcludeRegex().isBlank()) {
            validateRegex(dto.getExcludeRegex());
        }
        
        Pattern pattern = patternRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Pattern not found: " + id));

        pattern.setName(dto.getName());
        pattern.setRegex(dto.getRegex());
        pattern.setExcludeRegex(dto.getExcludeRegex());
        pattern.setSeverity(dto.getSeverity());
        pattern.setContextLines(dto.getContextLines());
        pattern.setDescription(dto.getDescription());
        pattern.setActive(dto.getActive());

        return toDto(patternRepository.save(pattern));
    }

    @Transactional
    public void delete(Long id) {
        patternRepository.deleteById(id);
    }

    /**
     * 정규식 패턴 테스트
     */
    public PatternTestResult testPattern(String regex, String sampleText) {
        try {
            java.util.regex.Pattern compiledPattern = java.util.regex.Pattern.compile(regex);
            java.util.regex.Matcher matcher = compiledPattern.matcher(sampleText);
            
            boolean found = matcher.find();
            String matchedText = found ? matcher.group() : null;
            int matchStart = found ? matcher.start() : -1;
            int matchEnd = found ? matcher.end() : -1;
            
            return new PatternTestResult(true, found, matchedText, matchStart, matchEnd, null);
        } catch (PatternSyntaxException e) {
            return new PatternTestResult(false, false, null, -1, -1, e.getMessage());
        }
    }

    private void validateRegex(String regex) {
        try {
            java.util.regex.Pattern.compile(regex);
        } catch (PatternSyntaxException e) {
            throw new RuntimeException("Invalid regex pattern: " + e.getMessage());
        }
    }

    private PatternDto toDto(Pattern pattern) {
        return PatternDto.builder()
                .id(pattern.getId())
                .name(pattern.getName())
                .regex(pattern.getRegex())
                .excludeRegex(pattern.getExcludeRegex())
                .severity(pattern.getSeverity())
                .contextLines(pattern.getContextLines())
                .description(pattern.getDescription())
                .active(pattern.getActive())
                .createdAt(pattern.getCreatedAt())
                .build();
    }

    public record PatternTestResult(
            boolean validRegex,
            boolean matched,
            String matchedText,
            int matchStart,
            int matchEnd,
            String errorMessage
    ) {}
}
