#!/usr/bin/python3


from __future__ import annotations

import logging
from pathlib import Path

from slpkg.config import config_load
from slpkg.package_validator import PackageValidator
from slpkg.utilities import Utilities

logger = logging.getLogger(__name__)


class ListFiles:  # pylint: disable=[R0902.R0903]
    """List files installed by one or more packages."""

    def __init__(self, options: dict[str, bool], packages: list[str]) -> None:
        logger.debug("Initializing ListFiles with packages: %s, options: %s", packages, options)
        self.packages = packages

        self.grey = config_load.grey
        self.green = config_load.green
        self.red = config_load.red
        self.endc = config_load.endc
        self.log_packages: Path = config_load.log_packages

        self.utils = Utilities()
        self.pkg_validator = PackageValidator()

        self.option_quiet: bool = options.get("option_quiet", False)
        self.option_no_case: bool = options.get("option_no_case", False)

    def _find_installed(self, name: str) -> str:
        """Return the full package filename for an installed package.

        Supports case-insensitive matching when option_no_case is set.

        Args:
            name (str): Package name to look up.

        Returns:
            str: Full package filename, or empty string if not found.
        """
        if self.option_no_case:
            name_lower = name.lower()
            for log_path in self.log_packages.iterdir():
                if self.utils.split_package(log_path.name)["name"].lower() == name_lower:
                    return log_path.name
            return ""
        return self.utils.is_package_installed(name)

    def _read_file_list(self, full_pkg_name: str) -> list[str]:
        """Read the FILE LIST section from a package log and return file paths.

        Skips directory entries and package install scripts.

        Args:
            full_pkg_name (str): Full package filename (e.g. ffmpeg-6.1-x86_64-1_SBo).

        Returns:
            list[str]: Sorted list of absolute file paths installed by the package.
        """
        pkg_log: Path = self.log_packages / full_pkg_name
        lines: list[str] = pkg_log.read_text(encoding="utf-8", errors="ignore").splitlines()

        try:
            idx: int = lines.index("FILE LIST:")
        except ValueError:
            logger.warning("No FILE LIST section found in '%s'.", pkg_log)
            return []

        files: list[str] = []
        for entry in lines[idx + 1:]:
            entry = entry.strip()
            if not entry or entry.endswith("/") or entry.startswith("install/"):
                continue
            # Normalise to absolute path: ./usr/... → /usr/..., usr/... → /usr/...
            if entry.startswith("./"):
                entry = entry[1:]
            elif not entry.startswith("/"):
                entry = f"/{entry}"
            files.append(entry)

        return files

    def run(self) -> None:
        """List files for each requested package."""
        for name in self.packages:
            full_pkg = self._find_installed(name)
            if not full_pkg:
                self.pkg_validator.is_package_installed([name])
                continue
            files = self._read_file_list(full_pkg)

            if self.option_quiet:
                print("\n".join(files))
            else:
                n = len(files)
                label = "file" if n == 1 else "files"
                print(f"Files installed by {self.green}{full_pkg}{self.endc}:\n")
                for f in files:
                    print(f"  {f}")
                print(f"\n{self.grey}Total: {n} {label}{self.endc}")
