#!/usr/bin/python3


import logging
import re
from pathlib import Path
from typing import Any

from slpkg.config import config_load
from slpkg.load_data import LoadData
from slpkg.repositories import Repositories
from slpkg.utilities import Utilities
from slpkg.views.display import View

logger = logging.getLogger(__name__)


class ImportPackages:  # pylint: disable=[R0902,R0903]
    """Imports and validates packages from a file."""

    def __init__(self, options: dict[str, Any]) -> None:
        self.options = options
        self.utils = Utilities()
        self.repos = Repositories()
        self.view = View(options)

        self.cyan = config_load.cyan
        self.red = config_load.red
        self.yellow = config_load.yellow
        self.endc = config_load.endc
        self.bold = config_load.bold

    def _parse_file(self, file_path: Path) -> dict[str, list[str]]:
        """Parse the .pkgs file and group packages by their repository header."""
        if not file_path.is_file():
            return {}

        try:
            content = file_path.read_text(encoding="utf-8")
            lines = content.splitlines()
        except (OSError, PermissionError) as e:
            logger.error("Failed to read import file %s: %s", file_path, e)
            return {}

        grouped_pkgs: dict[str, list[str]] = {}
        current_repo = "unknown"

        for line in lines:
            line = line.strip()
            if not line or (line.startswith("#") and not line.startswith("# [")):
                continue

            repo_match = re.match(r"^#\s*\[(.*?)\]", line)
            if repo_match:
                current_repo = repo_match.group(1).lower()
                continue

            if current_repo not in grouped_pkgs:
                grouped_pkgs[current_repo] = []

            pkg_name = line.split()[0]
            grouped_pkgs[current_repo].append(pkg_name)

        return grouped_pkgs

    def _validate_packages(self, grouped: dict[str, list[str]], all_repos_data: dict[str, Any]) -> dict[str, Any]:
        """Verify existence of packages and identify missing ones or disabled repos."""
        enabled_repos = set(all_repos_data.keys())
        missing_packages = []
        disabled_repos = set()
        to_install: dict[str, list[str]] = {}

        for tag, pkgs in grouped.items():
            clean_tag = tag.lower()
            target_repo = clean_tag if clean_tag in enabled_repos else ""

            for pkg in pkgs:
                found_in = self._find_package_repo(pkg, target_repo, all_repos_data)
                if found_in:
                    if found_in not in to_install:
                        to_install[found_in] = []
                    to_install[found_in].append(pkg)
                else:
                    missing_packages.append(pkg)
                    if tag != "unknown":
                        disabled_repos.add(tag)

        return {
            "to_install": to_install,
            "missing": missing_packages,
            "disabled_repos": disabled_repos
        }

    @staticmethod
    def _find_package_repo(pkg: str, target_repo: str, all_repos_data: dict[str, Any]) -> str:
        """Find which repository contains the specified package."""
        if target_repo and pkg in all_repos_data[target_repo]:
            return target_repo

        for r_name, r_data in all_repos_data.items():
            if pkg in r_data:
                return r_name
        return ""

    def _display_summary(self, total_in_file: int, results: dict[str, Any]) -> None:
        """Display the import summary and warnings."""
        if self.options.get("option_quiet"):
            return

        to_install = results["to_install"]
        print(f"\n{self.bold}Import Summary:{self.endc}")
        print(f"  - Total packages in file: {total_in_file}")
        print(f"  - Ready to install:       {sum(len(p) for p in to_install.values())}")

        if results["disabled_repos"]:
            print(f"\n{self.yellow}Warning{self.endc}: These repositories are required but DISABLED:")
            for r in sorted(results["disabled_repos"]):
                print(f"  - {r}")

        if results["missing"]:
            print(f"\n{self.red}Warning{self.endc}: These packages were NOT FOUND in any repository:")
            for p in sorted(results["missing"]):
                print(f"  - {p}")

    def run(self, filename: str) -> list[tuple[str, list[str]]]:
        """Main execution logic for import."""
        file_path = Path(filename)
        if file_path.suffix != ".pkgs":
            file_path = file_path.with_suffix(".pkgs")

        if not self.options.get("option_quiet"):
            print(f"{self.bold}Analyzing import file: {file_path}{self.endc}")

        grouped = self._parse_file(file_path)
        if not grouped:
            print(f"{self.red}Error{self.endc}: No valid packages found in file.")
            return []

        all_repos_data = LoadData().load("*", message=not self.options.get("option_quiet"))
        results = self._validate_packages(grouped, all_repos_data)

        self._display_summary(sum(len(p) for p in grouped.values()), results)

        if not results["to_install"]:
            if not self.options.get("option_quiet"):
                print(f"\n{self.red}Nothing to install.{self.endc}")
            return []

        if not self.options.get("option_quiet"):
            print(f"\n{self.bold}Installation Plan:{self.endc}")
            for repo, pkgs in results["to_install"].items():
                print(f"  - From {self.cyan}{repo}{self.endc}: {len(pkgs)} packages")

        # Respect -y/--yes option
        if not self.options.get("option_yes"):
            self.view.question("Do you want to proceed with the import?")

        return list(results["to_install"].items())
