"""
Copyright © 2025-2026 Omnissa, LLC.
"""

import logging
import os
import re
from logging.handlers import RotatingFileHandler

import coloredlogs

LOG_FORMAT_SIMPLE = "%(levelname).4s %(asctime)s %(name)-16s %(message)s"
LOG_FORMAT_LONG = (
    "%(color_on)s%(asctime)s.%(msecs)03d [%(process)-5d:%(threadName)-12s] %(levelname)-7s [%(name)-16s] %(message)s%(color_off)s"
)
DATE_FORMAT_SIMPLE = "%H:%M:%S"


def mask_password(msg: str) -> str:
    msg = re.sub(r"(\"password\"\s*:\s*\"?)(.*?)(\"?[\s*,? | \s*\}])", r"\1******\3", msg)
    return msg


class LogFormatter(logging.Formatter):
    COLOR_CODES = {
        logging.CRITICAL: "\033[1;35m",
        logging.ERROR: "\033[1;31m",
        logging.WARNING: "\033[1;33m",
        logging.INFO: "\033[0;37m",
        logging.DEBUG: "\033[1;30m",
    }

    RESET_CODE = "\033[0m"

    def __init__(self, color, mask, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.color = color
        self.mask = mask

    def format(self, record, *args, **kwargs):
        if self.color is True and record.levelno in self.COLOR_CODES:
            record.color_on = self.COLOR_CODES[record.levelno]
            record.color_off = self.RESET_CODE
        else:
            record.color_on = ""
            record.color_off = ""

        record.name = _shorten_package_name(record.name, 16)

        msg = super(LogFormatter, self).format(record, *args, **kwargs)
        return mask_password(msg) if self.mask else msg


class LogFormatterFixedNameWidth(logging.Formatter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def format(self, record, *args, **kwargs):
        record.name = _shorten_package_name(record.name, 16)
        return super(LogFormatterFixedNameWidth, self).format(record, *args, **kwargs)


def _shorten_package_name(package_name, max_length):
    if len(package_name) <= max_length:
        return package_name

    parts = package_name.split(".")
    shortened_parts = []

    for i, part in enumerate(parts):
        shortened_parts.append(part[0])

        if i == len(parts) - 1:
            # Last package name
            remaining_length = max_length - len(".".join(shortened_parts))
            if len(part) > remaining_length:
                shortened_parts[-1] = "..." + part[-remaining_length + 3 :]
            else:
                shortened_parts[-1] = part
        else:
            new_package_name = ".".join(shortened_parts)

            if len(new_package_name) + len(parts) - i - 1 > max_length:
                break

    return ".".join(shortened_parts)


def setup(
    console_log_output="stdout",
    console_log_level="INFO",
    console_log_color=True,
    console_log_mask=True,
    logfile_file=None,
    logfile_log_level="INFO",
    logfile_log_color=False,
    logfile_log_mask=True,
    log_line_template=LOG_FORMAT_SIMPLE,
    date_fmt=DATE_FORMAT_SIMPLE,
):
    # Alternative: 'global logger; logger = logging.getLogger("<name>")'
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    if console_log_output is not None:
        setup_console_output(
            logger,
            console_log_output,
            console_log_level,
            console_log_color,
            console_log_mask,
            log_line_template,
            date_fmt,
        )

    if logfile_file:
        setup_file_output(
            logger,
            logfile_file,
            logfile_log_level,
            logfile_log_color,
            logfile_log_mask,
            log_line_template,
        )


def setup_console_output(logger, console_log_output, console_log_level, console_log_color, console_log_mask, log_line_template, date_fmt):
    if not date_fmt:
        date_fmt = coloredlogs.DEFAULT_DATE_FORMAT
    coloredlogs.install(
        level=console_log_level,
        fmt=log_line_template,
        datefmt=date_fmt,
        formatter=LogFormatter(fmt=log_line_template, color=console_log_color, mask=console_log_mask),
    )

    # console_log_output = console_log_output.lower()
    # if console_log_output == "stdout":
    #     console_log_output = sys.stdout
    # elif console_log_output == "stderr":
    #     console_log_output = sys.stderr
    # else:
    #     raise Exception("Failed to set console output: invalid output: '%s'" % console_log_output)
    # console_handler = logging.StreamHandler(console_log_output)

    # try:
    #     console_handler.setLevel(console_log_level.upper())
    # except:
    #     print("Failed to set console log level: invalid level: '%s'" % console_log_level)
    #     raise

    # console_formatter = LogFormatter(fmt=log_line_template, color=console_log_color, mask=console_log_mask)
    # console_handler.setFormatter(console_formatter)
    # logger.addHandler(console_handler)


def setup_file_output(
    logger,
    logfile_file,
    logfile_log_level,
    logfile_log_color,
    logfile_log_mask,
    log_line_template,
):
    logfile_max_bytes = 50 * 1024 * 1024
    logfile_max_count = 20
    try:
        logfile_handler = RotatingFileHandler(logfile_file, maxBytes=logfile_max_bytes, backupCount=logfile_max_count)
    except Exception as exception:
        print("Failed to set up log file: %s" % str(exception))
        raise

    try:
        logfile_handler.setLevel(logfile_log_level.upper())
    except Exception:
        print("Failed to set log file log level: invalid level: '%s'" % logfile_log_level)
        raise

    logfile_formatter = LogFormatter(fmt=log_line_template, color=logfile_log_color, mask=logfile_log_mask)
    logfile_handler.setFormatter(logfile_formatter)
    logger.addHandler(logfile_handler)


def get(file_name):
    return logging.getLogger(os.path.basename(os.path.splitext(file_name)[0]))
