"""File manager module for handling logging to a file."""

import os

from ..exceptions import FileError


class FileManager:
    """
    A simple class for handling logging to a file.

    :param file_path: The path to the file where logs should be written.
    :type file_path: str
    :param mode: File open mode (default: 'a' = append).
    :type mode: str
    :param max_size: If > 0, triggers a simple log rotation if file grows
        beyond this (bytes).
    :type max_size: int
    """

    def __init__(self, file_path: str, mode: str = "a", max_size: int = 0) -> None:
        """
        Constructor that opens the file.

        :param file_path: The path to the file where logs are written.
        :type file_path: str
        :param mode: File open mode.
        :type mode: str
        :param max_size: If > 0, triggers simple rotation if file exceeds this size.
        :type max_size: int
        :raises FileError: If the file cannot be opened.
        """
        self.file_path = file_path
        self.mode = mode
        self.max_size = max_size
        try:
            self._file = open(self.file_path, self.mode, encoding="utf-8")
        except OSError as e:
            raise FileError(f"Failed to open file {
                            file_path}: {str(e)}") from e

    def write_line(self, line: str) -> None:
        """
        Writes a line to the file and flushes immediately, rotating if needed.

        :param line: The line (log message) to write.
        :type line: str
        :raises FileError: If write fails.
        """
        try:
            self._file.write(line + "\n")
            self._file.flush()
            if self.max_size > 0:
                self._check_rotate()
        except OSError as e:
            raise FileError(
                "Failed to write to file "
                f"{self.file_path}: {str(e)}"
            ) from e

    def close(self) -> None:
        """
        Closes the file. Further writes will fail.
        """
        if not self._file.closed:
            self._file.close()

    def _check_rotate(self) -> None:
        """
        Simple rotation approach if file size exceeds max_size.
        (Rename current file with .bak, create new empty file.)
        """
        current_size = os.path.getsize(self.file_path)
        if current_size > self.max_size > 0:
            self._file.close()
            backup_path = self.file_path + ".bak"
            # Overwrite the old .bak if exists.
            if os.path.exists(backup_path):
                os.remove(backup_path)
            os.rename(self.file_path, backup_path)
            # Re-open a fresh file.
            self._file = open(self.file_path, "w", encoding="utf-8")
