#!/usr/bin/python3
"""Tests for slpkg.blacklist.Blacklist and slpkg.blacklist_cmd.BlacklistCmd."""

from pathlib import Path
from unittest.mock import MagicMock

import pytest

from slpkg.blacklist import Blacklist
from slpkg.blacklist_cmd import BlacklistCmd
from slpkg.toml_errors import TomlErrors

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def make_blacklist(toml_file: Path) -> Blacklist:
    """Construct Blacklist bypassing __init__ (avoids config_load)."""
    bl: Blacklist = object.__new__(Blacklist)
    bl.blacklist_file_toml = toml_file
    bl.toml_errors = TomlErrors()
    return bl


def make_cmd(packages: list[str], *, quiet: bool = False) -> BlacklistCmd:
    """Construct BlacklistCmd bypassing __init__ with mocked dependencies."""
    cmd: BlacklistCmd = object.__new__(BlacklistCmd)
    cmd.blacklist_file = Path("/etc/slpkg/blacklist.toml")
    cmd.bold = cmd.grey = cmd.cyan = cmd.green = cmd.endc = ""
    cmd.quiet = quiet
    cmd.black = MagicMock()
    cmd.black.packages.return_value = packages
    return cmd


# ---------------------------------------------------------------------------
# Blacklist.packages() — file does not exist
# ---------------------------------------------------------------------------


def test_packages_returns_empty_when_file_missing(tmp_path: Path) -> None:
    bl = make_blacklist(tmp_path / "blacklist.toml")
    assert bl.packages() == []


# ---------------------------------------------------------------------------
# Blacklist.packages() — valid content
# ---------------------------------------------------------------------------


def test_packages_returns_list(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text('PACKAGES = ["ffmpeg", "vlc"]\n', encoding="utf-8")
    bl = make_blacklist(f)
    assert bl.packages() == ["ffmpeg", "vlc"]


def test_packages_single_entry(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text('PACKAGES = ["bash"]\n', encoding="utf-8")
    bl = make_blacklist(f)
    assert bl.packages() == ["bash"]


def test_packages_empty_list(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text("PACKAGES = []\n", encoding="utf-8")
    bl = make_blacklist(f)
    assert bl.packages() == []


def test_packages_values_are_strings(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text('PACKAGES = ["ffmpeg", "vlc", "x264"]\n', encoding="utf-8")
    bl = make_blacklist(f)
    assert all(isinstance(p, str) for p in bl.packages())


def test_packages_preserves_order(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text('PACKAGES = ["zzz", "aaa", "mmm"]\n', encoding="utf-8")
    bl = make_blacklist(f)
    assert bl.packages() == ["zzz", "aaa", "mmm"]


# ---------------------------------------------------------------------------
# Blacklist.packages() — missing or wrong-type key
# ---------------------------------------------------------------------------


def test_packages_missing_key_returns_empty(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text('OTHER = ["ffmpeg"]\n', encoding="utf-8")
    bl = make_blacklist(f)
    assert bl.packages() == []


def test_packages_key_not_a_list_returns_empty(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text('PACKAGES = "ffmpeg"\n', encoding="utf-8")
    bl = make_blacklist(f)
    assert bl.packages() == []


# ---------------------------------------------------------------------------
# Blacklist.packages() — invalid TOML → SystemExit
# ---------------------------------------------------------------------------


def test_packages_invalid_toml_raises_systemexit(tmp_path: Path) -> None:
    f = tmp_path / "blacklist.toml"
    f.write_text("PACKAGES = [this is not valid toml\n", encoding="utf-8")
    bl = make_blacklist(f)
    with pytest.raises(SystemExit):
        bl.packages()


# ---------------------------------------------------------------------------
# BlacklistCmd.view() — empty list
# ---------------------------------------------------------------------------


def test_view_empty_prints_header(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd([])
    cmd.view()
    out = capsys.readouterr().out
    assert "Blacklisted packages" in out


def test_view_empty_prints_not_found(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd([])
    cmd.view()
    out = capsys.readouterr().out
    assert "No blacklisted packages found." in out


def test_view_empty_prints_file_path(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd([])
    cmd.view()
    out = capsys.readouterr().out
    assert "blacklist.toml" in out


def test_view_empty_quiet_prints_nothing(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd([], quiet=True)
    cmd.view()
    assert capsys.readouterr().out == ""


# ---------------------------------------------------------------------------
# BlacklistCmd.view() — packages present
# ---------------------------------------------------------------------------


def test_view_prints_each_package(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["vlc", "ffmpeg"])
    cmd.view()
    out = capsys.readouterr().out
    assert "vlc" in out
    assert "ffmpeg" in out


def test_view_packages_sorted(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["zzz", "aaa", "mmm"])
    cmd.view()
    out = capsys.readouterr().out
    assert out.index("aaa") < out.index("mmm") < out.index("zzz")


def test_view_prints_count_plural(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["vlc", "ffmpeg"])
    cmd.view()
    out = capsys.readouterr().out
    assert "2" in out
    assert "packages" in out


def test_view_prints_count_singular(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["vlc"])
    cmd.view()
    out = capsys.readouterr().out
    assert "1 blacklisted package." in out
    assert "1 blacklisted packages." not in out


def test_view_prints_file_path_when_packages_present(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["vlc"])
    cmd.view()
    out = capsys.readouterr().out
    assert "blacklist.toml" in out


# ---------------------------------------------------------------------------
# BlacklistCmd.view() — quiet mode with packages
# ---------------------------------------------------------------------------


def test_view_quiet_prints_only_names(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["vlc", "ffmpeg"], quiet=True)
    cmd.view()
    lines = capsys.readouterr().out.splitlines()
    assert sorted(lines) == ["ffmpeg", "vlc"]


def test_view_quiet_no_header(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["vlc"], quiet=True)
    cmd.view()
    out = capsys.readouterr().out
    assert "Blacklisted packages" not in out


def test_view_quiet_no_count(capsys: pytest.CaptureFixture) -> None:
    cmd = make_cmd(["vlc", "ffmpeg"], quiet=True)
    cmd.view()
    out = capsys.readouterr().out
    assert "Found" not in out
