from __future__ import annotations

from types import TracebackType
from typing import Self

import pytest
from fastapi import Request
from starlette.responses import Response

from pygitweb.api.action import Action
from pygitweb.api.subpage import Subpage


def test_action_subclass_wrong_return_annotation() -> None:
	with pytest.raises(TypeError, match="missing or mismatched 'action'"):

		class BadAction(Action):
			def __enter__(self) -> Self:
				return self

			def __exit__(
				self,
				exc_type: type[BaseException] | None,
				exc_value: BaseException | None,
				traceback: TracebackType | None,
			) -> bool | None:
				return None

			def action_name(self) -> str:
				return "bad"

			def action(self, project: str, req: Request | None = None) -> int:
				return 1


def test_action_subclass_missing_exit() -> None:
	with pytest.raises(TypeError, match="missing or mismatched '__exit__'"):

		class BadAction(Action):
			def __enter__(self) -> Self:
				return self

			def action_name(self) -> str:
				return "bad"

			def action(self, project: str, req: Request | None = None) -> Response | None:
				return None


def test_subpage_subclass_wrong_return_annotation() -> None:
	with pytest.raises(TypeError, match="missing or mismatched 'subpage_name'"):

		class BadSubpage(Subpage):
			def __enter__(self) -> Self:
				return self

			def __exit__(
				self,
				exc_type: type[BaseException] | None,
				exc_value: BaseException | None,
				traceback: TracebackType | None,
			) -> bool | None:
				return None

			def subpage_name(self) -> int:
				return 1

			def link_name(self, project: str) -> str | None:
				return None

			def subpage_html(self, project: str) -> str | None:
				return None

			def summary_value_suffix_html(self, project: str, project_enc: str) -> str | None:
				return None


def test_action_virtual_register_non_compliant() -> None:
	class Bad:
		def __enter__(self) -> Self:
			return self

		def __exit__(
			self,
			exc_type: type[BaseException] | None,
			exc_value: BaseException | None,
			traceback: TracebackType | None,
		) -> bool | None:
			return None

		def action_name(self) -> str:
			return "bad"

		def action(self, project: str, req: Request | None = None) -> int:
			return 1

	with pytest.raises(TypeError, match="missing or mismatched 'action'"):
		Action.register(Bad)