from __future__ import annotations

import os
import unittest
from unittest.mock import MagicMock, patch

from scripts import publish_gitea


class GiteaTokenTests(unittest.TestCase):
    def test_reads_ignored_token_file(self) -> None:
        token_file = MagicMock()
        token_file.is_file.return_value = True
        token_file.read_text.return_value = "local-token\n"
        with (
            patch.dict(os.environ, {}, clear=True),
            patch.object(publish_gitea, "GITEA_TOKEN_FILE", token_file),
        ):
            self.assertEqual(publish_gitea.gitea_token(), "local-token")

    def test_environment_token_overrides_file(self) -> None:
        token_file = MagicMock()
        with (
            patch.dict(os.environ, {"GITEA_TOKEN": "environment-token"}, clear=True),
            patch.object(publish_gitea, "GITEA_TOKEN_FILE", token_file),
        ):
            self.assertEqual(publish_gitea.gitea_token(), "environment-token")
        token_file.is_file.assert_not_called()

    def test_requires_token(self) -> None:
        token_file = MagicMock()
        token_file.is_file.return_value = False
        with (
            patch.dict(os.environ, {}, clear=True),
            patch.object(publish_gitea, "GITEA_TOKEN_FILE", token_file),
        ):
            with self.assertRaisesRegex(SystemExit, "Gitea token is required"):
                publish_gitea.gitea_token()


class CreateReleaseTests(unittest.TestCase):
    def test_retries_postgres_tag_sync_collision(self) -> None:
        collision = publish_gitea.GiteaAPIError(
            "POST",
            "/repos/phenom/i-want-to-heal-mmo/releases",
            500,
            'duplicate key violates "UQE_release_n" (23505)',
        )
        created = {"id": 15, "tag_name": "v0.1.15"}

        with (
            patch.object(publish_gitea, "release_for_tag", return_value=None),
            patch.object(
                publish_gitea,
                "gitea_request",
                side_effect=[collision, created],
            ) as request,
            patch.object(publish_gitea.time, "sleep") as sleep,
        ):
            result = publish_gitea.create_release(
                "v0.1.15",
                "ea5d455",
                "Release v0.1.15 2026-07-18",
                "token",
            )

        self.assertEqual(result, created)
        self.assertEqual(request.call_count, 2)
        sleep.assert_called_once_with(0.5)

    def test_does_not_retry_unrelated_api_error(self) -> None:
        unauthorized = publish_gitea.GiteaAPIError(
            "POST",
            "/repos/phenom/i-want-to-heal-mmo/releases",
            401,
            "unauthorized",
        )

        with (
            patch.object(publish_gitea, "release_for_tag", return_value=None),
            patch.object(
                publish_gitea,
                "gitea_request",
                side_effect=unauthorized,
            ) as request,
            patch.object(publish_gitea.time, "sleep") as sleep,
        ):
            with self.assertRaises(publish_gitea.GiteaAPIError):
                publish_gitea.create_release(
                    "v0.1.16",
                    "commit",
                    "Release v0.1.16",
                    "token",
                )

        request.assert_called_once()
        sleep.assert_not_called()


if __name__ == "__main__":
    unittest.main()
