#!/usr/bin/python3


from __future__ import annotations

import json
import logging
from pathlib import Path

from slpkg.config import config_load

logger = logging.getLogger(__name__)

# Maps each action to a terminal color attribute name on config_load.
_ACTION_COLOR: dict[str, str] = {
    "install": "green",
    "upgrade": "yellow",
    "reinstall": "cyan",
    "build": "bold",
    "remove": "red",
}

# Fixed display width (columns).
_WIDTH: int = 79
_SEP: str = "=" * _WIDTH

# Column widths.  Total: 1 + _TW + 2 + _AW + 2 + _NW + 2 + _VW + 2 + _RW = 79.
_TW: int = 5  # Time       (HH:MM)
_AW: int = 9  # Action     (reinstall)
_NW: int = 24  # Name
_VW: int = 18  # Version
_RW: int = 14  # Repository (right-aligned)


class History:  # pylint: disable=[R0902,R0914]
    """Reads and displays the slpkg package operation history."""

    def __init__(self, limit: int = 0, package: str = "", option_json: bool = False) -> None:
        """
        Args:
            limit:       Maximum number of entries to display (0 = all).
            package:     If non-empty, show only entries for this package name (case-insensitive).
            option_json: When True, output entries as a JSON array instead of formatted text.
        """
        self.history_log_file: Path = config_load.history_log_file
        self.limit = limit
        self.package = package.lower()
        self.option_json = option_json
        self.green = config_load.green
        self.yellow = config_load.yellow
        self.red = config_load.red
        self.cyan = config_load.cyan
        self.grey = config_load.grey
        self.bold = config_load.bold
        self.endc = config_load.endc

    def _action_color(self, action: str) -> str:
        return getattr(self, _ACTION_COLOR.get(action, ""), "")

    def _trunc(self, value: str, width: int) -> str:
        """Truncate value to width, appending '...' if necessary."""
        if len(value) > width:
            return value[: width - 3] + "..."
        return value

    def clear(self) -> None:
        """Delete the history log file."""
        logger.info("Clearing history log: %s", self.history_log_file)
        self.history_log_file.unlink(missing_ok=True)
        print(f"History log cleared: {self.history_log_file}")

    def view(self) -> None:  # pylint: disable=[R0915]
        """Display history entries grouped by date, oldest first."""
        logger.debug("Displaying history from '%s' (limit=%d).", self.history_log_file, self.limit)

        if not self.history_log_file.is_file() or self.history_log_file.stat().st_size == 0:
            logger.info("History log not found or empty: %s", self.history_log_file)
            print(f"{self.bold}Package Operation History{self.endc}")
            print(_SEP)
            print(" No package operation history found.")
            print(_SEP)
            return

        raw_lines = self.history_log_file.read_text(encoding="utf-8").splitlines()

        entries: list[list[str]] = []
        for line in raw_lines:
            parts = [p.strip() for p in line.split("|")]
            if len(parts) == 5:
                entries.append(parts)

        if not entries:
            logger.info("History log contains no parseable entries.")
            print(f"{self.bold}Package Operation History{self.endc}")
            print(_SEP)
            print(" No package operation history found.")
            print(_SEP)
            return

        if self.package:
            entries = [e for e in entries if e[2].lower() == self.package]
            logger.debug("Entries after filtering by package '%s': %d.", self.package, len(entries))

        total: int = len(entries)
        logger.debug("Total history entries: %d.", total)

        if self.limit > 0:
            entries = entries[-self.limit:]
            logger.debug("Entries after applying limit of %d: %d.", self.limit, len(entries))

        if self.option_json:
            results = [
                {
                    "timestamp": timestamp,
                    "date": timestamp[:10],
                    "time": timestamp[11:] if len(timestamp) > 10 else "",
                    "action": action,
                    "name": name,
                    "version": version,
                    "repository": repo,
                }
                for timestamp, action, name, version, repo in entries
            ]
            print(json.dumps(results, indent=2))
            logger.info("History JSON output completed. Entries: %d.", len(results))
            return

        # Header.
        title = f"Package Operation History — {self.package}" if self.package else "Package Operation History"
        print(f"{self.bold}{title}{self.endc}")
        print(_SEP)
        print(
            f" {self.bold}{self.cyan}"
            f"{'Time':<{_TW}}  {'Action':<{_AW}}  {'Name':<{_NW}}  {'Version':<{_VW}}  {'Repository':>{_RW}}"
            f"{self.endc}"
        )
        print(_SEP)

        current_date = ""
        for timestamp, action, name, version, repo in entries:
            date = timestamp[:10]
            if date != current_date:
                current_date = date
                print(f"\n{self.bold} {date}{self.endc}")

            time_part = timestamp[11:] if len(timestamp) > 10 else ""
            color = self._action_color(action)
            name = self._trunc(name, _NW)
            version = self._trunc(version, _VW)
            print(
                f" {time_part:<{_TW}}  {color}{action:<{_AW}}{self.endc}  {name:<{_NW}}  {version:<{_VW}}  {repo:>{_RW}}"
            )

        # Footer.
        print(f"\n{_SEP}")
        shown = len(entries)
        if self.limit > 0 and shown < total:
            footer = f" {shown} of {total} entries  \u00b7  {self.history_log_file}"
        else:
            noun = "entry" if total == 1 else "entries"
            footer = f" {total} {noun}  \u00b7  {self.history_log_file}"
        print(f"{self.grey}{footer}{self.endc}")

        logger.info("History display completed. Showed %d of %d entries.", shown, total)
