"""
Logging utilities and helper functions.
"""

import logging
import sys
from datetime import datetime
from typing import Optional

from config import LOG_LEVEL, LOG_FILE, LOG_TO_CONSOLE, LOG_TO_FILE, DATE_FORMAT


# Global logger instance
_logger: Optional[logging.Logger] = None


def setup_logging(
    name: str = "trading_bot",
    level: str = LOG_LEVEL,
    log_file: str = LOG_FILE,
    console: bool = LOG_TO_CONSOLE,
    file: bool = LOG_TO_FILE
) -> logging.Logger:
    """
    Setup and configure logging.

    Args:
        name: Logger name
        level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
        log_file: Path to log file
        console: Enable console logging
        file: Enable file logging

    Returns:
        Configured logger instance
    """
    global _logger

    logger = logging.getLogger(name)
    logger.setLevel(getattr(logging, level.upper(), logging.INFO))

    # Clear existing handlers
    logger.handlers.clear()

    # Create formatter
    formatter = logging.Formatter(
        "%(asctime)s | %(levelname)-8s | %(message)s",
        datefmt=DATE_FORMAT
    )

    # Console handler
    if console:
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(formatter)
        logger.addHandler(console_handler)

    # File handler
    if file:
        file_handler = logging.FileHandler(log_file)
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

    _logger = logger
    return logger


def get_logger() -> logging.Logger:
    """
    Get the global logger instance.

    Returns:
        Logger instance (creates one if not exists)
    """
    global _logger
    if _logger is None:
        _logger = setup_logging()
    return _logger


def log_trade(
    action: str,
    symbol: str,
    price: float,
    lots: float,
    magic: int = 0,
    tp: Optional[float] = None,
    sl: Optional[float] = None,
    profit: Optional[float] = None
) -> None:
    """
    Log a trade action.

    Args:
        action: Trade action (BUY, SELL, CLOSE, etc.)
        symbol: Trading pair symbol
        price: Execution price
        lots: Position size
        magic: Magic number (thread ID)
        tp: Take profit price
        sl: Stop loss price
        profit: Realized profit/loss
    """
    logger = get_logger()
    msg = f"[TRADE] {action} {symbol} @ {price:.8f} | Lots: {lots:.6f} | Magic: {magic}"

    if tp is not None:
        msg += f" | TP: {tp:.8f}"
    if sl is not None:
        msg += f" | SL: {sl:.8f}"
    if profit is not None:
        msg += f" | P/L: {profit:.2f}"

    logger.info(msg)


def log_thread_event(
    event: str,
    magic: int,
    details: str = ""
) -> None:
    """
    Log a thread-related event.

    Args:
        event: Event type (CREATED, AVERAGING, CLOSED, etc.)
        magic: Thread magic number
        details: Additional event details
    """
    logger = get_logger()
    msg = f"[THREAD] {event} | Magic: {magic}"
    if details:
        msg += f" | {details}"
    logger.info(msg)


def log_balance(
    balance: float,
    equity: float,
    margin_used: float = 0.0,
    open_positions: int = 0
) -> None:
    """
    Log account balance information.

    Args:
        balance: Account balance
        equity: Account equity
        margin_used: Used margin
        open_positions: Number of open positions
    """
    logger = get_logger()
    logger.info(
        f"[BALANCE] Balance: {balance:.2f} | Equity: {equity:.2f} | "
        f"Margin: {margin_used:.2f} | Positions: {open_positions}"
    )


def format_price(price: float, decimals: int = 8) -> str:
    """
    Format price for display.

    Args:
        price: Price value
        decimals: Number of decimal places

    Returns:
        Formatted price string
    """
    return f"{price:.{decimals}f}"


def format_lots(lots: float) -> str:
    """
    Format lot size for display.

    Args:
        lots: Lot size value

    Returns:
        Formatted lot size string
    """
    return f"{lots:.6f}"


def timestamp_now() -> datetime:
    """
    Get current timestamp.

    Returns:
        Current datetime
    """
    return datetime.now()


def timestamp_to_str(dt: datetime) -> str:
    """
    Convert datetime to string.

    Args:
        dt: Datetime object

    Returns:
        Formatted datetime string
    """
    return dt.strftime(DATE_FORMAT)


def str_to_timestamp(date_str: str) -> datetime:
    """
    Parse datetime from string.

    Args:
        date_str: Datetime string

    Returns:
        Datetime object
    """
    return datetime.strptime(date_str, DATE_FORMAT)


def calculate_percentage_change(old_value: float, new_value: float) -> float:
    """
    Calculate percentage change between two values.

    Args:
        old_value: Original value
        new_value: New value

    Returns:
        Percentage change
    """
    if old_value == 0:
        return 0.0
    return ((new_value - old_value) / old_value) * 100


def safe_division(numerator: float, denominator: float, default: float = 0.0) -> float:
    """
    Perform safe division with default value for division by zero.

    Args:
        numerator: Division numerator
        denominator: Division denominator
        default: Default value if denominator is zero

    Returns:
        Division result or default
    """
    if denominator == 0:
        return default
    return numerator / denominator
