import logging
from logging.handlers import RotatingFileHandler, BaseRotatingHandler
import os
import glob
import traceback
import inspect


class Logger1():

    def __init__(self, log_file="ITServer.log", logger_name="MainLogger", 
                 file_log_level=logging.DEBUG):
        """
        Logger 초기화
        :param log_file: 로그 파일 이름
        :param logger_name: 로거 이름
        :param file_log_level: 파일 로거의 로그 레벨
        """
        super().__init__()
        self.file_log_level = file_log_level

        # 로그 설정
        self.logger = logging.getLogger(logger_name)
        self.logger.setLevel(file_log_level)  # 파일 로거 레벨 설정

        # 포맷 설정
        self.simple_format = "[%(asctime)s] [%(levelname)s] %(message)s"
        self.detailed_format = (
            "[%(asctime)s] [%(threadName)s] [%(levelname)s] "
            "[%(filename)s:%(funcName)s:%(lineno)d] %(message)s"
        )

        # 핸들러 추가
        self._add_console_handler(file_log_level)
        self._add_file_handler(log_file, file_log_level)

    def _add_console_handler(self, level):
        """콘솔 핸들러 추가"""
        console_handler = logging.StreamHandler()
        console_handler.setLevel(level)
        formatter = logging.Formatter(
            self.detailed_format if level <= logging.DEBUG else self.simple_format
        )
        console_handler.setFormatter(formatter)
        self.logger.addHandler(console_handler)

    def _add_file_handler(self, log_file, level):
        """파일 핸들러 추가"""
        # 확장자가 .log가 아니면 .log로 변경
        if not log_file.endswith('.log'):
            base_name, _ = os.path.splitext(log_file)
            log_file = base_name + '.log'
            
        # 커스텀 로테이팅 핸들러 사용
        file_handler = CustomRotatingFileHandler(
            log_file, maxBytes=10 * 1024 * 1024, backupCount=5, encoding="utf-8"
        )
        file_handler.setLevel(level)
        formatter = logging.Formatter(
            self.detailed_format if level <= logging.DEBUG else self.simple_format
        )
        file_handler.setFormatter(formatter)
        self.logger.addHandler(file_handler)
        
    def log(self, message, level=logging.INFO, exc_info=False):
        """로그 메시지 기록"""
        if exc_info:
            message = f"{message}\n{traceback.format_exc()}"

        # 호출 위치 정보를 동적으로 추출
        caller_frame = logging.currentframe().f_back
        record = self.logger.makeRecord(
            self.logger.name, level, caller_frame.f_code.co_filename, 
            caller_frame.f_lineno, message, None, None, caller_frame.f_code.co_name
        )

        # 파일 로거에 메시지 전달
        if level >= self.file_log_level:
            self.logger.handle(record)

class CustomRotatingFileHandler(BaseRotatingHandler):
    """로그 파일을 모두 .log 확장자로 생성하는 커스텀 핸들러"""
    
    def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None):
        super().__init__(filename, mode, encoding)
        self.maxBytes = maxBytes
        self.backupCount = backupCount
        # 기존 로그 파일 확인 및 인덱스 설정
        self._base_filename = filename
        self._extension = '.log'
        
    def doRollover(self):
        """롤오버 수행 - 파일이 최대 크기에 도달하면 새 파일 생성"""
        if self.stream:
            self.stream.close()
            self.stream = None
            
        # 기존 로그 파일 이름을 기반으로 백업 파일 생성
        base_name, ext = os.path.splitext(self._base_filename)
        
        # 현재 디렉토리의 모든 로그 파일 확인
        log_dir = os.path.dirname(self._base_filename) or '.'
        existing_logs = glob.glob(f"{base_name}*.log")
        existing_logs.sort()
        
        # 최대 백업 수 초과하는 파일 제거
        while len(existing_logs) >= self.backupCount:
            try:
                oldest_file = existing_logs.pop(0)
                os.remove(oldest_file)
            except Exception:
                pass
                
        # 새 로그 파일 이름 생성 (주 로그 파일 이름은 그대로 유지)
        # 예: log.log, log_1.log, log_2.log, ...
        if os.path.exists(self._base_filename):
            # 인덱스가 있는 로그 파일들 찾기
            indexed_logs = [f for f in existing_logs if f != self._base_filename]
            max_index = 0
            
            for log_file in indexed_logs:
                try:
                    # 파일 이름에서 인덱스 부분 추출
                    name_part = os.path.basename(log_file)
                    name_without_ext = os.path.splitext(name_part)[0]
                    if '_' in name_without_ext:
                        idx_str = name_without_ext.split('_')[-1]
                        if idx_str.isdigit():
                            max_index = max(max_index, int(idx_str))
                except Exception:
                    pass
                    
            # 새 인덱스로 파일 이름 설정
            new_index = max_index + 1
            new_log_file = f"{base_name}_{new_index}.log"
            
            # 기존 파일 이름 변경
            try:
                os.rename(self._base_filename, new_log_file)
            except Exception:
                pass
                
        # 스트림 다시 열기
        self.mode = 'w'
        self.stream = self._open()
            
    def shouldRollover(self, record):
        """롤오버가 필요한지 확인"""
        if self.stream is None:  # 첫 번째 로그 쓰기 시도
            self.stream = self._open()
            
        if self.maxBytes > 0:  # 최대 크기가 지정된 경우만 검사
            self.stream.seek(0, 2)  # 파일 끝으로 이동
            if self.stream.tell() >= self.maxBytes:
                return True
        return False
