"""
로그 수집을 위한 Python logging Handler
모든 로그 레벨을 자동으로 캡처하여 Producer로 전송함

역할: Python logger에 자동으로 추가되어 모든 로그를 수집함
사용: MonitoringSDK.init()에서 logger에 자동 등록됨
"""

import logging
from datetime import datetime
from typing import Optional
from ..types.interfaces import LogEntry
from ..transport.batch_sender import BatchSender
from ..tracing.trace_context import get_current_trace_id


class LogCollectorHandler(logging.Handler):
    """
    로그 수집을 위한 logging.Handler
    """

    def __init__(
        self,
        batch_sender: BatchSender,
        service_name: str,
        environment: str
    ):
        """
        LogCollectorHandler 초기화

        Args:
            batch_sender: 배치 전송자
            service_name: 서비스 이름
            environment: 환경 설정
        """
        super().__init__()
        self.batch_sender = batch_sender
        self.service_name = service_name
        self.environment = environment

    def emit(self, record: logging.LogRecord) -> None:
        """
        Python에서 로그가 발생할 때마다 호출됨

        역할:
        1. Python에서 전달된 로그 정보를 받음
        2. LogEntry 형식으로 변환함
        3. BatchSender에 추가함

        사용: logger.log(), logger.error(), logger.warning() 등 모든 로그에서 자동 호출됨

        Args:
            record: logging.LogRecord 객체
        """
        # httpx, urllib3 로그 무시 (무한 루프 방지)
        if record.name.startswith(('httpx', 'urllib3', 'httpcore')):
            return

        try:
            # 현재 trace context에서 trace_id 가져오기
            trace_id = get_current_trace_id()

            log_entry: LogEntry = {
                'type': 'log',
                'timestamp': datetime.utcnow().isoformat() + 'Z',
                'service_name': self.service_name,
                'environment': self.environment,
                'level': record.levelname.lower(),
                'message': self.format(record),
                'context': record.name,
                'trace': self._get_trace_info(record),
                'trace_id': trace_id  # 트레이스 도중이면 trace_id, 아니면 None
            }

            self.batch_sender.add(log_entry)
        except Exception:
            # 로그 수집 실패가 앱에 영향을 주지 않도록 무시
            self.handleError(record)

    def _get_trace_info(self, record: logging.LogRecord) -> Optional[str]:
        """
        로그 레코드에서 트레이스 정보를 추출함

        Args:
            record: logging.LogRecord 객체

        Returns:
            트레이스 정보 문자열 또는 None
        """
        if hasattr(record, 'exc_info') and record.exc_info:
            return self.formatter.formatException(record.exc_info) if self.formatter else None
        if hasattr(record, 'stack_info') and record.stack_info:
            return record.stack_info
        return None
