"""Unit tests for tools.view_history.utils."""

from unittest.mock import patch

import pytest

from tools.view_history.utils import (
    format_timestamp,
    get_project_name,
    normalize_affected_files,
)


# ---------------------------------------------------------------------------
# normalize_affected_files
# ---------------------------------------------------------------------------

class TestNormalizeAffectedFiles:
    def test_empty_list(self):
        assert normalize_affected_files([]) == []

    def test_none_input(self):
        assert normalize_affected_files(None) == []

    def test_strings(self):
        assert normalize_affected_files(["a.py", "b.py"]) == ["a.py", "b.py"]

    def test_dicts_with_file_path(self):
        items = [{"file_path": "src/a.py"}, {"file_path": "src/b.py"}]
        assert normalize_affected_files(items) == ["src/a.py", "src/b.py"]

    def test_dicts_with_path(self):
        items = [{"path": "c.py"}]
        assert normalize_affected_files(items) == ["c.py"]

    def test_dicts_prefer_file_path_over_path(self):
        items = [{"file_path": "preferred.py", "path": "other.py"}]
        assert normalize_affected_files(items) == ["preferred.py"]

    def test_dicts_with_empty_values_skipped(self):
        items = [{"file_path": "", "path": ""}]
        assert normalize_affected_files(items) == []

    def test_mixed_types(self):
        items = ["a.py", {"file_path": "b.py"}, 42]
        assert normalize_affected_files(items) == ["a.py", "b.py", "42"]

    def test_other_types_converted_via_str(self):
        assert normalize_affected_files([123, True]) == ["123", "True"]


# ---------------------------------------------------------------------------
# get_project_name
# ---------------------------------------------------------------------------

class TestGetProjectName:
    def test_none_input(self):
        assert get_project_name(None) is None

    def test_empty_string(self):
        assert get_project_name("") is None

    @patch("tools.view_history.utils.subprocess.run")
    def test_git_success(self, mock_run):
        mock_run.return_value.returncode = 0
        mock_run.return_value.stdout = "/home/user/my-repo\n"
        assert get_project_name("/home/user/my-repo") == "my-repo"

    @patch("tools.view_history.utils.subprocess.run")
    def test_git_failure_falls_back(self, mock_run):
        mock_run.return_value.returncode = 128
        assert get_project_name("/home/user/my-folder") == "my-folder"

    @patch("tools.view_history.utils.subprocess.run", side_effect=FileNotFoundError)
    def test_git_not_installed(self, mock_run):
        assert get_project_name("/home/user/my-dir") == "my-dir"

    def test_path_object(self):
        from pathlib import Path
        with patch("tools.view_history.utils.subprocess.run") as mock_run:
            mock_run.return_value.returncode = 0
            mock_run.return_value.stdout = "/tmp/repo\n"
            assert get_project_name(Path("/tmp/repo")) == "repo"


# ---------------------------------------------------------------------------
# format_timestamp
# ---------------------------------------------------------------------------

class TestFormatTimestamp:
    # full (default)
    def test_full_iso(self):
        assert format_timestamp("2026-01-29T14:30:45.123") == "2026-01-29 14:30:45"

    def test_full_no_millis(self):
        assert format_timestamp("2026-01-29T14:30:45") == "2026-01-29 14:30:45"

    # time
    def test_time_style(self):
        assert format_timestamp("2026-01-29T14:30:45.123", "time") == "14:30:45"

    # short
    def test_short_style(self):
        result = format_timestamp("2026-01-29T14:30:45", "short")
        assert "Jan" in result
        assert "29" in result

    # date
    def test_date_style(self):
        result = format_timestamp("2026-01-29T14:30:45", "date")
        assert "Jan" in result
        assert "2026" in result

    # edge cases
    def test_empty_string(self):
        assert format_timestamp("") == "Unknown"

    def test_none_handled(self):
        assert format_timestamp(None) == "Unknown"

    def test_z_suffix(self):
        assert format_timestamp("2026-01-29T14:30:45Z") == "2026-01-29 14:30:45"

    def test_unparseable_falls_back(self):
        result = format_timestamp("not-a-date")
        assert isinstance(result, str)

    def test_date_only_string(self):
        result = format_timestamp("2026-01-29", "date")
        assert "Jan" in result
        assert "2026" in result
