#!/usr/bin/python3
"""Tests for slpkg.cleanup.Cleanings."""

from pathlib import Path
from unittest.mock import MagicMock, patch

from slpkg.cleanup import Cleanings


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


def make_cleanings(tmp_path: Path) -> Cleanings:
    """Construct Cleanings bypassing __init__ (avoids config_load/View)."""
    obj: Cleanings = object.__new__(Cleanings)
    obj.tmp_slpkg = tmp_path / "slpkg"
    obj.build_path = tmp_path / "slpkg" / "build"
    obj.bold = ""
    obj.red = ""
    obj.endc = ""
    obj.view = MagicMock()
    return obj


# ---------------------------------------------------------------------------
# tmp() — no files
# ---------------------------------------------------------------------------


def test_tmp_no_files_prints_message_and_returns(tmp_path: Path, capsys) -> None:
    obj = make_cleanings(tmp_path)
    obj.tmp_slpkg.mkdir(parents=True)
    obj.tmp()
    out = capsys.readouterr().out
    assert "No files or folders to delete" in out
    obj.view.question.assert_not_called()


# ---------------------------------------------------------------------------
# tmp() — symlink protection
# ---------------------------------------------------------------------------


def test_tmp_symlink_outside_tmp_refuses_deletion(tmp_path: Path, capsys) -> None:
    obj = make_cleanings(tmp_path)
    # Point tmp_slpkg to a path that resolves outside /tmp/
    obj.tmp_slpkg = tmp_path / "slpkg"
    obj.tmp_slpkg.mkdir(parents=True)
    (obj.tmp_slpkg / "somefile.txt").write_text("data", encoding="utf-8")

    with patch.object(Path, "resolve", return_value=Path("/var/cache/slpkg")):
        obj.tmp()

    out = capsys.readouterr().out
    assert "Refusing to delete" in out
    obj.view.question.assert_not_called()


# ---------------------------------------------------------------------------
# tmp() — files present, user confirms
# ---------------------------------------------------------------------------


def test_tmp_files_present_calls_question(tmp_path: Path, capsys) -> None:
    obj = make_cleanings(tmp_path)
    obj.tmp_slpkg = tmp_path / "tmp" / "slpkg"
    obj.build_path = obj.tmp_slpkg / "build"
    obj.tmp_slpkg.mkdir(parents=True)
    (obj.tmp_slpkg / "pkg.txz").write_text("data", encoding="utf-8")

    with patch.object(Path, "resolve", return_value=Path("/tmp/slpkg")):
        obj.tmp()

    obj.view.question.assert_called_once()


def test_tmp_removes_directory_and_recreates_build(tmp_path: Path, capsys) -> None:
    obj = make_cleanings(tmp_path)
    obj.tmp_slpkg = tmp_path / "tmp" / "slpkg"
    obj.build_path = obj.tmp_slpkg / "build"
    obj.tmp_slpkg.mkdir(parents=True)
    (obj.tmp_slpkg / "pkg.txz").write_text("data", encoding="utf-8")

    with patch.object(Path, "resolve", return_value=Path("/tmp/slpkg")):
        obj.tmp()

    # build_path is recreated after rmtree
    assert obj.build_path.is_dir()
    out = capsys.readouterr().out
    assert "Successfully cleared" in out


# ---------------------------------------------------------------------------
# tmp() — OSError on rmtree
# ---------------------------------------------------------------------------


def test_tmp_rmtree_oserror_prints_error(tmp_path: Path, capsys) -> None:
    import shutil
    obj = make_cleanings(tmp_path)
    obj.tmp_slpkg = tmp_path / "tmp" / "slpkg"
    obj.build_path = obj.tmp_slpkg / "build"
    obj.tmp_slpkg.mkdir(parents=True)
    (obj.tmp_slpkg / "pkg.txz").write_text("data", encoding="utf-8")

    with patch.object(Path, "resolve", return_value=Path("/tmp/slpkg")):
        with patch.object(shutil, "rmtree", side_effect=OSError("permission denied")):
            obj.tmp()

    out = capsys.readouterr().out
    assert "Error" in out
    assert "Successfully cleared" not in out


# ---------------------------------------------------------------------------
# tmp() — OSError on mkdir (build_path recreation)
# ---------------------------------------------------------------------------


def test_tmp_mkdir_oserror_prints_error(tmp_path: Path, capsys) -> None:
    import shutil
    obj = make_cleanings(tmp_path)
    obj.tmp_slpkg = tmp_path / "tmp" / "slpkg"
    obj.build_path = obj.tmp_slpkg / "build"
    obj.tmp_slpkg.mkdir(parents=True)
    (obj.tmp_slpkg / "pkg.txz").write_text("data", encoding="utf-8")

    with patch.object(Path, "resolve", return_value=Path("/tmp/slpkg")):
        with patch.object(Path, "mkdir", side_effect=OSError("read only")):
            obj.tmp()

    out = capsys.readouterr().out
    assert "Error" in out
    assert "Successfully cleared" not in out
