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.plugin_registry import PluginHandle, PluginRegistry, current_plugin_id, plugin_load_context


def test_plugin_load_context_sets_current_plugin() -> None:
	previous = current_plugin_id()
	with plugin_load_context("demo"):
		assert current_plugin_id() == "demo"
	assert current_plugin_id() == previous


def test_plugin_handle_unload_exits_context() -> None:
	events: list[str] = []

	class Tracked(Action):
		def __enter__(self) -> Self:
			events.append("enter")
			return self

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

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

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

	import contextlib

	stack = contextlib.ExitStack()
	stack.enter_context(plugin_load_context("tracked"))
	instance = stack.enter_context(Tracked())
	handle = PluginHandle(plugin_id="tracked", _stack=stack, instance=instance)
	assert current_plugin_id() == "tracked"
	assert events == ["enter"]
	handle.unload()
	assert events == ["enter", "exit"]
	assert current_plugin_id() != "tracked"


def test_plugin_registry_load_and_unload() -> None:
	registry = PluginRegistry()
	registry.load_all()
	registry.unload_all()