import logging
import sys
import threading
from logging.handlers import RotatingFileHandler
from pathlib import Path
from typing import Optional

from alayaflow.common.config import settings


FILE_ONLY_KEY = "_file_only"

class AlayaFlowLogger:
    _instance: Optional[logging.Logger] = None
    _lock: threading.Lock = threading.Lock()

    def __new__(cls) -> logging.Logger:
        if cls._instance is None:
            with cls._lock:
                # Double-check locking
                if cls._instance is None:
                    cls._instance = logging.getLogger("alayaflow")
                    cls._initialize_logger(cls._instance)
        return cls._instance

    @classmethod
    def _initialize_logger(cls, logger: logging.Logger):
        if logger.hasHandlers():
            logger.handlers.clear()
        
        logger.setLevel(settings.log_level)
        logger.propagate = False

        formatter = logging.Formatter(
            "[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d][pid:%(process)d] - %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )

        cls._add_console_handler(logger, formatter)
        cls._add_safe_file_handler(logger, formatter)

    @staticmethod
    def _add_console_handler(logger: logging.Logger, formatter: logging.Formatter):
        console = logging.StreamHandler(stream=sys.stderr)
        console.setFormatter(formatter)

        console.addFilter(lambda r: not getattr(r, FILE_ONLY_KEY, False))
        
        if not settings.is_dev():
            console.setLevel(logging.ERROR)

        logger.addHandler(console)

    @staticmethod
    def _add_safe_file_handler(logger: logging.Logger, formatter: logging.Formatter):
        """尝试添加文件 Handler，如果失败（如权限问题）则仅记录一次警告"""
        log_dir = Path(settings.log_dir)
        log_path = log_dir / "alayaflow.log"

        try:
            log_dir.mkdir(parents=True, exist_ok=True)
            
            file_handler = RotatingFileHandler(
                log_path, 
                maxBytes=10 * 1024 * 1024, # 10MB
                backupCount=5,
                encoding='utf-8'
            )
            file_handler.setFormatter(formatter)
            file_handler.setLevel(logging.DEBUG if settings.is_dev() else logging.INFO)
            logger.addHandler(file_handler)
            
        except (PermissionError, OSError) as e:
            logger.warning(
                "[AlayaFlowLogger] Cannot open log file under %s (%s); "
                "logging will rely on console output.",
                log_dir,
                e,
            )
