"""Refactored code to address pylint warnings/hints

- Added docstrings to methods missing them (C0116)
- Split lines to keep them <= 80 characters (C0301)
- Provided setter/getter methods to avoid protected-access usage (W0212)

For real-world usage, consider a .pylintrc with adjusted line length (like 88)
or explicit allows if you need direct protected references.
"""

from typing import Callable, Optional

from app.constants import LogLevel, TextColor
from app.file_manager import FileManager
from app.logging import LogManager, LoggingController
from app.progress_bar import ProgressBar, ProgressController
from app.screen_renderer import ScreenRenderer


class RichLogger:
    """
    A high-level facade that coordinates:
      - LoggingController for logging
      - ProgressController for progress
      - ScreenRenderer for drawing everything

    It acts as a convenient single-point interface.
    """

    def __init__(
        self,
        level: LogLevel = LogLevel.INFO,
        total_steps: int = 20,
        bar_length: int = 30,
        fill_char: str = "#",
        empty_char: str = "-",
        prefix: str = "",
        suffix: str = "",
        file_path: Optional[str] = None,
        file_mode: str = "a",
        file_level: Optional[LogLevel] = None,
        console_formatter: Optional[
            Callable[[LogLevel, str, str, TextColor], str]
        ] = None,
        file_formatter: Optional[Callable[[LogLevel, str, str], str]] = None,
        fill_color: Optional[TextColor] = None,
        empty_color: Optional[TextColor] = None,
        non_destructive: bool = False,
        thread_safe: bool = False,
        time_format: str = "%Y-%m-%d %H:%M:%S",
        show_eta: bool = False,
        max_file_size: int = 0
    ) -> None:
        """
        Initializes the RichLogger facade, setting up:
        - ScreenRenderer
        - LogManager + LoggingController
        - ProgressBar + ProgressController
        """
        self._renderer = ScreenRenderer(
            non_destructive=non_destructive,
            thread_safe=thread_safe
        )

        fm: Optional[FileManager] = None
        if file_path:
            fm = FileManager(file_path, file_mode, max_size=max_file_size)

        self._log_manager = LogManager(
            console_level=level,
            file_level=file_level if file_level else level,
            file_manager=fm,
            console_formatter=console_formatter,
            file_formatter=file_formatter,
            time_format=time_format,
            thread_safe=thread_safe
        )
        self._logging_controller = LoggingController(self._log_manager)

        progress_bar = ProgressBar(
            total_steps=total_steps if total_steps > 0 else 1,
            bar_length=bar_length,
            fill_char=fill_char,
            empty_char=empty_char,
            prefix=prefix,
            suffix=suffix,
            fill_color=fill_color or TextColor.RESET,
            empty_color=empty_color or TextColor.RESET,
            show_eta=show_eta
        )
        self._progress_controller = ProgressController(progress_bar)

        self._redraw_screen()

    def log(self, level: LogLevel, message: str,
            color: TextColor = TextColor.RESET) -> None:
        """Logs a message at the given level, then redraws if logged."""
        timestamp = self._logging_controller.log(level, message, color)
        if timestamp is not None:
            self._redraw_screen()

    def debug(self, message: str, color: TextColor = TextColor.RESET) -> None:
        """Shortcut to log with DEBUG level."""
        self.log(LogLevel.DEBUG, message, color)

    def info(self, message: str, color: TextColor = TextColor.RESET) -> None:
        """Shortcut to log with INFO level."""
        self.log(LogLevel.INFO, message, color)

    def warning(self, message: str, color: TextColor = TextColor.RESET) -> None:
        """Shortcut to log with WARNING level."""
        self.log(LogLevel.WARNING, message, color)

    def error(self, message: str, color: TextColor = TextColor.RESET) -> None:
        """Shortcut to log with ERROR level."""
        self.log(LogLevel.ERROR, message, color)

    def critical(self, message: str,
                 color: TextColor = TextColor.RESET) -> None:
        """Shortcut to log with CRITICAL level."""
        self.log(LogLevel.CRITICAL, message, color)

    def log_multiline(self,
                      level: LogLevel,
                      text_block: str,
                      color: TextColor = TextColor.RESET) -> None:
        """Logs multiple lines from a text block, splitting by newlines."""
        self._logging_controller.log_multiline(level, text_block, color)
        self._redraw_screen()

    def clear_logs(self) -> None:
        """Clears all in-memory logs and triggers a redraw."""
        self._logging_controller.clear_logs()
        self._redraw_screen()

    def close_file(self) -> None:
        """Closes the file manager if it is in use."""
        self._logging_controller.close_file()

    def set_progress(self, step: int) -> None:
        """Sets the progress bar to a specific step count."""
        self._progress_controller.set_progress(step)
        self._redraw_screen()

    def increment_progress(self, inc: int = 1) -> None:
        """Increments the progress bar by the given amount."""
        self._progress_controller.increment_progress(inc)
        self._redraw_screen()

    def reset_progress(self, total_steps: int = 100) -> None:
        """Resets the progress to zero, optionally with a new total."""
        self._progress_controller.reset_progress(total_steps)
        self._redraw_screen()

    def _redraw_screen(self) -> None:
        """
        Fetches the current log lines and progress bar text, then uses
        ScreenRenderer to display them.
        """
        log_lines = self._logging_controller.get_lines()
        bar_text = self._progress_controller.build_bar_text()
        self._renderer.redraw(log_lines, bar_text)

    # region Accessors to avoid protected-access issues
    @property
    def logging_controller(self) -> LoggingController:
        """Getter for the LoggingController."""
        return self._logging_controller

    @logging_controller.setter
    def logging_controller(self, controller: LoggingController) -> None:
        """Setter for the LoggingController."""
        self._logging_controller = controller

    @property
    def progress_controller(self) -> ProgressController:
        """Getter for the ProgressController."""
        return self._progress_controller

    @progress_controller.setter
    def progress_controller(self, controller: ProgressController) -> None:
        """Setter for the ProgressController."""
        self._progress_controller = controller

    @property
    def renderer(self) -> ScreenRenderer:
        """Getter for the ScreenRenderer."""
        return self._renderer

    @renderer.setter
    def renderer(self, new_renderer: ScreenRenderer) -> None:
        """Setter for the ScreenRenderer."""
        self._renderer = new_renderer

    @property
    def log_manager(self) -> LogManager:
        """Getter for the underlying LogManager."""
        return self._log_manager

    @log_manager.setter
    def log_manager(self, manager: LogManager) -> None:
        """Setter for the underlying LogManager."""
        self._log_manager = manager

    # endregion

    def create_child_logger(
        self,
        console_level: Optional[LogLevel] = None,
        file_level: Optional[LogLevel] = None
    ) -> "RichLogger":
        """
        Demonstrates how we might create a child logger, using the
        underlying LogManager's `create_child_logger()`. The child
        shares the same file manager, but can have different levels.
        """
        child_lm = self.log_manager.create_child_logger(console_level,
                                                        file_level)
        child = RichLogger(
            level=self.log_manager.console_level,
            total_steps=self.progress_controller.total_steps,
            bar_length=0,
            fill_char="#",
            empty_char="-",
            prefix="",
            suffix="",
            file_path=None,
            file_level=child_lm.file_level,
        )
        # Use setters to avoid direct protected access
        child.log_manager = child_lm
        child.logging_controller = LoggingController(child_lm)
        child.progress_controller = self.progress_controller
        child.renderer = self.renderer
        return child
