"""
VOC 텍스트 파싱 및 정보 추출 유틸리티

이 모듈은 VOC(Voice of Customer) 제목과 내용에서 구조화된 정보를 추출합니다.
정규식 기반 패턴 매칭과 문맥 분석을 통해 호선, 편성, 호차, 열차번호 등의
핵심 정보를 자동으로 파싱합니다.

주요 기능:
    - 기본 정보 추출: 호선, 편성, 호차, 열차번호
    - 문맥 기반 유추: 역명으로 호선 유추, 방향성 키워드 분석
    - 시간 정보 추출: HH:MM 형식 시간 파싱
    - 열차번호 재검색: 키워드 기반 보조 검색
    - 제목 정제: 파일명용 제목 생성
    - 내용 포맷팅: 키워드 기반 논리적 줄바꿈

리팩토링 배경:
    기존 ReportService(1056줄)에서 VOC 파싱 로직을 분리하여
    단일 책임 원칙을 준수하고 재사용성을 높였습니다.

사용 예시:
    >>> parser = VOCParser(stations_list=["서면", "부산역", "해운대"])
    >>> full_text = "1호선 10편성 1호차 서면역에서 소음 발생"
    >>> info = parser.parse_basic_info(full_text)
    >>> print(info)
    {'line': '1호선', 'set': '10편성', 'car': '1호차', 'train': ''}
    
    >>> line, direction, station = parser.infer_line_and_direction(full_text)
    >>> print(f"호선: {line}, 방향: {direction}, 역: {station}")
    호선: 1호선, 방향: , 역: 서면

작성자: KH.Choi
최종 수정: 2026-02-17
버전: 2.0 (ReportService에서 분리)
"""
import re


class VOCParser:
    """
    VOC 텍스트에서 구조화된 정보를 추출하는 파서
    
    이 클래스는 자연어로 작성된 VOC 내용을 분석하여 보고서 작성에 필요한
    구조화된 데이터를 추출합니다. 정규식 패턴 매칭과 문맥 분석을 통해
    명시적으로 언급되지 않은 정보도 유추할 수 있습니다.
    
    Attributes:
        stations (list): 역명 리스트. 호선 유추 및 방향 판별에 사용됩니다.
    
    주요 메서드:
        parse_basic_info: 호선, 편성, 호차, 열차번호 추출
        infer_line_and_direction: 문맥 기반 호선/방향 유추
        extract_time: 시간 정보 추출
        search_train_number_in_context: 열차번호 재검색
        sanitize_title_for_filename: 파일명용 제목 정제
        format_voc_content: VOC 내용 포맷팅
    
    사용 시나리오:
        1. ReportService에서 보고서 생성 시 VOC 데이터 파싱
        2. 자동화된 정보 추출로 사용자 입력 부담 감소
        3. 일관된 파싱 로직으로 데이터 품질 향상
    
    예시:
        >>> parser = VOCParser(["서면", "부산역"])
        >>> text = "2월 13일 17:34 서면역 노포행 열차에서 소음"
        >>> time = parser.extract_time(text)
        >>> print(time)
        17:34
    """
    
    def __init__(self, stations_list=None):
        """
        Args:
            stations_list (list): 역명 리스트 (호선 유추용)
        """
        self.stations = stations_list or []
    
    def parse_basic_info(self, full_text):
        """
        기본 정보 추출 (호선, 편성, 호차, 열차번호)
        
        Args:
            full_text (str): 제목 + 본문 합친 텍스트
            
        Returns:
            dict: {"line": "1호선", "set": "10편성", "car": "1호차", "train": "1215"}
        """
        patterns = {
            "line": r"(\d+)\s*호선",
            "set": r"(\d+)\s*편성",
            "car": r"(\d+)\s*호차",
            "train": r"(?:열차번호|제|열번|열차|T|S)\s*(\d{4})|(\d{4})\s*(?:열차)"
        }
        
        info = {k: "" for k in patterns}
        
        for k, p in patterns.items():
            match = re.search(p, full_text)
            if match:
                val = match.group(1) if match.lastindex >= 1 else match.group(0)
                
                if k == "train":
                    # 그룹들 중 4자리 숫자 찾기
                    for g in match.groups():
                        if g and g.isdigit() and len(g) == 4:
                            val = g
                            break
                
                if k == "line":
                    info[k] = f"{val}호선"
                elif k == "set":
                    info[k] = f"{val}편성"
                elif k == "car":
                    info[k] = f"{val}호차"
                else:
                    info[k] = val
        
        return info
    
    def infer_line_and_direction(self, full_text):
        """
        문맥에서 호선과 방향 유추
        
        Args:
            full_text (str): 제목 + 본문
            
        Returns:
            tuple: (호선, 방향, 발견된역명)
        """
        inferred_line = ""
        inferred_dir = ""
        found_station = ""
        
        # 1. 역명 검색으로 호선 유추
        for station in self.stations:
            if station in full_text:
                inferred_line = "1호선"
                found_station = station
                break
        
        # 2. 방향성 유추
        # Case A: "XX방향" 직접 언급
        direction_match = re.search(r"(\w+역?)\s*방향", full_text)
        if direction_match:
            dir_word = direction_match.group(1)
            if "노포" in dir_word:
                inferred_dir = "노포행(하선)"
            elif "다대포" in dir_word:
                inferred_dir = "다대포행(상선)"
        
        # Case A-1: "XX행" 언급
        if not inferred_dir:
            dest_match = re.search(r"(\w+)\s*행", full_text)
            if dest_match:
                dest_word = dest_match.group(1)
                if "노포" in dest_word:
                    inferred_dir = "노포행(하선)"
                elif "다대포" in dest_word:
                    inferred_dir = "다대포행(상선)"
        
        # Case B: "A역에서 타서 B역에서 내림" 이동 경로 분석
        ride_match = re.search(r"(\w+역?)\s*에서\s*타서\s*(\w+역?)\s*에서\s*내렸", full_text)
        if ride_match and not inferred_dir:
            start_st = ride_match.group(1).replace("역", "")
            end_st = ride_match.group(2).replace("역", "")
            
            if start_st in self.stations and end_st in self.stations:
                start_idx = self.stations.index(start_st)
                end_idx = self.stations.index(end_st)
                inferred_dir = "노포행(하선)" if start_idx < end_idx else "다대포행(상선)"
        
        return inferred_line, inferred_dir, found_station
    
    def extract_time(self, full_text):
        """
        시간 정보 추출 (HH:MM)
        
        Args:
            full_text (str): 텍스트
            
        Returns:
            str: "17:34" 형식의 시간 또는 빈 문자열
        """
        time_match = re.search(r"(\d{1,2})\s*[:시]\s*(\d{1,2})", full_text)
        if time_match:
            return f"{int(time_match.group(1)):02d}:{int(time_match.group(2)):02d}"
        return ""
    
    def search_train_number_in_context(self, full_text):
        """
        본문에서 열차번호 재검색 (키워드 기반)
        
        Args:
            full_text (str): 텍스트
            
        Returns:
            str: 열차번호 또는 빈 문자열
        """
        # 명확한 키워드와 함께 있는 경우
        t_match = re.search(r"(?:열차|열번|번호)\s*(\d{4})", full_text)
        if t_match:
            extracted = t_match.group(1)
            # 전화번호 패턴인지 확인
            phone_check = re.search(fr"[\d-]*{extracted}[\d-]*", full_text)
            if phone_check:
                chk_str = phone_check.group(0)
                if '-' not in chk_str and len(chk_str) == 4:
                    return extracted
        return ""
    
    def sanitize_title_for_filename(self, title):
        """
        파일명용 제목 정제 (호선, 편성 등 제거)
        
        Args:
            title (str): 원본 제목
            
        Returns:
            str: 정제된 제목
        """
        formatted_title = title
        for pat in [r'\d+\s*호선', r'\d+\s*편성', r'\d+\s*호차', r'제?\d{4}열차', r'[,]']:
            formatted_title = re.sub(pat, '', formatted_title)
        return re.sub(r'\s+', ' ', formatted_title).strip()
    
    def format_voc_content(self, title, content):
        """
        VOC 내용 포맷팅 (키워드 기반 줄바꿈)
        
        Args:
            title (str): 제목
            content (str): 본문
            
        Returns:
            str: 포맷팅된 텍스트
        """
        if not content:
            content = ""
        
        # 1. 기초 텍스트 구성
        raw_text = f"□ 제목 : {title}\r\n\r\n{content}"
        
        # 2. 불규칙한 줄바꿈 정리
        text = re.sub(r'[\r\n]+', ' ', raw_text).strip()
        text = re.sub(r'\s+', ' ', text)
        
        # 3. 키워드 패턴 정의
        patterns = [
            (r'((?:▶\s*)?\d{2}/\d{2}\s*\d{2}:\d{2}(?:\s*(?:전화|문자)\s*수신내용)?)', r'\r\n\r\n\1'),
            (r'(□\s*민원인\s*[:])', r'\r\n\1'),
            (r'(문자\s*답신내용\s*[:]|전화내용\s*[:])', r'\r\n\1'),
            (r'(답변내용\s*[:])', r'\r\n\1'),
            (r'(처리결과\d*\)\))', r'\r\n\1'),
            (r'(확인내용\d*\)\))', r'\r\n\1'),
            (r'(참고사항\)\))', r'\r\n\1'),
            (r'(※)', r'\r\n\1'),
        ]
        
        # 4. 패턴 적용
        formatted_text = text
        for pat, repl in patterns:
            formatted_text = re.sub(pat, repl, formatted_text)
        
        # 5. 후처리
        lines = formatted_text.split('\r\n')
        final_lines = [line.strip() for line in lines if line.strip()]
        
        return "\r\n".join(final_lines).replace("\r\n\r\n\r\n", "\r\n\r\n")
