"""Tests for autobuilder_hook_helpers.github."""

import json
import subprocess
import sys
from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest

sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "hook-helpers"))

from autobuilder_hook_helpers.github import (
    get_ci_failure_logs,
    get_github_remote,
    get_head_sha,
    get_latest_workflow_run,
    has_github_workflows,
)


class TestGetGithubRemote:
    def test_ssh_url(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(
                stdout="git@github.com:owner/repo.git\n",
                returncode=0,
            )
            result = get_github_remote(tmp_path)
        assert result == ("owner", "repo")

    def test_https_url(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(
                stdout="https://github.com/myorg/myrepo.git\n",
                returncode=0,
            )
            result = get_github_remote(tmp_path)
        assert result == ("myorg", "myrepo")

    def test_no_remote(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(stdout="", returncode=1)
            result = get_github_remote(tmp_path)
        assert result is None

    def test_non_github_remote(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(
                stdout="git@gitlab.com:org/repo.git\n",
                returncode=0,
            )
            result = get_github_remote(tmp_path)
        assert result is None

    def test_exception(self, tmp_path):
        with patch("subprocess.run", side_effect=OSError("fail")):
            result = get_github_remote(tmp_path)
        assert result is None


class TestHasGithubWorkflows:
    def test_has_workflows(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(stdout="3\n", returncode=0)
            assert has_github_workflows(tmp_path, "owner", "repo") is True

    def test_no_workflows(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(stdout="0\n", returncode=0)
            assert has_github_workflows(tmp_path, "owner", "repo") is False

    def test_api_failure(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(stdout="", returncode=1)
            assert has_github_workflows(tmp_path, "owner", "repo") is False


class TestGetLatestWorkflowRun:
    def test_found(self, tmp_path):
        run_data = {"id": 123, "status": "completed", "conclusion": "success"}
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(
                stdout=json.dumps(run_data) + "\n",
                returncode=0,
            )
            result = get_latest_workflow_run(
                tmp_path, "owner", "repo", "abc123",
            )
        assert result == run_data

    def test_not_found(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(stdout="null\n", returncode=0)
            result = get_latest_workflow_run(
                tmp_path, "owner", "repo", "abc123",
            )
        assert result is None

    def test_empty_output(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(stdout="", returncode=0)
            result = get_latest_workflow_run(
                tmp_path, "owner", "repo", "abc123",
            )
        assert result is None


class TestGetHeadSha:
    def test_returns_sha(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(
                stdout="abc123def456\n", returncode=0,
            )
            assert get_head_sha(tmp_path) == "abc123def456"

    def test_fallback(self, tmp_path):
        with patch("subprocess.run", side_effect=OSError("fail")):
            assert get_head_sha(tmp_path) == ""


class TestGetCiFailureLogs:
    def test_returns_logs(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(
                stdout="Error in step build\nFailed\n", returncode=0,
            )
            logs = get_ci_failure_logs(tmp_path, "owner", "repo", 42)
        assert "Error in step build" in logs

    def test_truncates_long_logs(self, tmp_path):
        long_log = "x" * 20000
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(
                stdout=long_log, returncode=0,
            )
            logs = get_ci_failure_logs(tmp_path, "owner", "repo", 42)
        assert len(logs) <= 8100
        assert logs.startswith("... (truncated)")

    def test_empty_on_failure(self, tmp_path):
        with patch("subprocess.run") as mock_run:
            mock_run.return_value = MagicMock(stdout="", returncode=1)
            logs = get_ci_failure_logs(tmp_path, "owner", "repo", 42)
        assert logs == ""
