from types import SimpleNamespace

from pdftl.core.types import OpResult
from pdftl.utils import hooks


def test_get_output_path_priorities():
    """Test resolution order of output path (Lines 16-29)."""

    # 1. stage.options['output']
    stage = SimpleNamespace(options={"output": "path1"})
    assert hooks._get_output_path(stage) == "path1"

    # 4. None
    stage = SimpleNamespace(options={})
    assert hooks._get_output_path(stage) is None


def test_text_dump_hook_scenarios(capsys, tmp_path):
    """Test text_dump_hook behavior (Lines 37-51)."""

    stage = SimpleNamespace(options={})
    # 1. Failure or empty data -> Return early
    hooks.text_dump_hook(OpResult(success=False), stage)
    out, _ = capsys.readouterr()
    assert out == ""

    hooks.text_dump_hook(OpResult(success=True, data=""), stage)
    out, _ = capsys.readouterr()
    assert out == ""

    # 2. No output path -> Stdout
    res = OpResult(success=True, data="stdout content")
    stage = SimpleNamespace(options={})
    hooks.text_dump_hook(res, stage)
    out, _ = capsys.readouterr()
    assert "stdout content" in out

    # 3. Output path -> File
    output_file = tmp_path / "output.txt"
    stage = SimpleNamespace(options={"output": str(output_file)})
    hooks.text_dump_hook(res, stage)

    assert output_file.exists()
    assert output_file.read_text().strip() == "stdout content"


def test_json_dump_hook_scenarios(capsys, tmp_path):
    """Test json_dump_hook behavior (Lines 59-72)."""

    data = {"key": "value"}
    res = OpResult(success=True, data=data)

    # 1. Stdout
    stage = SimpleNamespace(options={})
    hooks.json_dump_hook(res, stage)
    out, _ = capsys.readouterr()
    assert '"key": "value"' in out

    # 2. File
    output_file = tmp_path / "output.json"
    stage = SimpleNamespace(options={"output": str(output_file)})
    hooks.json_dump_hook(res, stage)

    assert output_file.exists()
    assert '"key": "value"' in output_file.read_text()

    # 3. Failure -> No op
    hooks.json_dump_hook(OpResult(success=False), None)
    # Implicit pass if no error raised


from unittest.mock import MagicMock

import pytest

from pdftl.utils.hooks import str_from_result_meta, text_dump_hook


def test_text_dump_hook_early_returns():
    """Test that text_dump_hook returns early on failure or empty data."""
    stage = MagicMock()

    # Case 1: Failure
    res_fail = OpResult(success=False, data="Some error")
    # Should simply return None, not print, not write file
    assert text_dump_hook(res_fail, stage) is None

    # Case 2: No Data
    res_no_data = OpResult(success=True, data=None)
    assert text_dump_hook(res_no_data, stage) is None


def test_str_from_result_meta():
    """Test the meta string extraction utility."""
    # Case 1: Valid String
    res = OpResult(success=True, meta={"key": "value"})
    assert str_from_result_meta(res, "key") == "value"

    # Case 2: Missing Key (AssertionError from from_result_meta or None check)
    # The code asserts result.meta is not None.
    # But if key is missing, .get returns None, failing isinstance(None, str)
    with pytest.raises(AssertionError):
        str_from_result_meta(res, "missing_key")

    # Case 3: Wrong Type
    res_int = OpResult(success=True, meta={"key": 123})
    with pytest.raises(AssertionError):
        str_from_result_meta(res_int, "key")
