import logging
import os
import sys
from datetime import datetime
from logging.handlers import RotatingFileHandler
from typing import override
from zoneinfo import ZoneInfo

from dotenv import find_dotenv, load_dotenv

load_dotenv(find_dotenv())

LOG_FILE_PATH = os.getenv("LOG_FILE_PATH")
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
LOG_FORMAT = (
    "[%(asctime)s] [%(levelname)s] %(name)s [%(process)d:%(threadName)s] %(message)s"
)


class LocalTimeFormatter(logging.Formatter):
    @override
    def converter(self, timestamp):
        dt = datetime.fromtimestamp(timestamp, tz=ZoneInfo("UTC"))
        return dt.astimezone(ZoneInfo("Asia/Kathmandu")).timetuple()

    @override
    def formatTime(self, record, datefmt=None):
        dt = datetime.fromtimestamp(record.created, tz=ZoneInfo("UTC"))
        ktm_dt = dt.astimezone(ZoneInfo("Asia/Kathmandu"))
        if datefmt:
            return ktm_dt.strftime(datefmt)
        return ktm_dt.isoformat(sep=" ", timespec="milliseconds")


def setup_logging():
    """Configures Root and Uvicorn loggers. Call ONCE in main.py."""
    root_logger = logging.getLogger()

    if root_logger.hasHandlers():
        return

    root_logger.setLevel(LOG_LEVEL)

    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(LocalTimeFormatter(LOG_FORMAT))

    file_handler = None
    if LOG_FILE_PATH:
        try:
            abs_log_path = os.path.abspath(LOG_FILE_PATH)
            os.makedirs(os.path.dirname(abs_log_path), exist_ok=True)
            file_handler = RotatingFileHandler(
                abs_log_path, maxBytes=10 * 1024 * 1024, backupCount=5
            )
            file_handler.setFormatter(logging.Formatter(LOG_FORMAT))
            print(f"--- LOGGING TO FILE: {abs_log_path} ---", flush=True)
        except Exception as e:
            print(f"CRITICAL: Failed to setup file logging: {e}", flush=True)

    root_logger.addHandler(console_handler)
    if file_handler:
        root_logger.addHandler(file_handler)


def get_logger(name: str):
    return logging.getLogger(name)
