from __future__ import annotations

from iisi_app_core.context import principal
from iisi_app_core.handlers.event import ApiGatewayEventHandler, EventBridgeEventHandler


class DummyJwtHandler:
    def __init__(self) -> None:
        self.calls = 0

    def __call__(self, event) -> None:
        self.calls += 1


class DummyCorsHandler:
    def __init__(self) -> None:
        self.calls = 0

    def apply(self, event, response):
        self.calls += 1
        return response


class DummyRestHandler:
    def __init__(self, can_handle_result: bool = True) -> None:
        self.can_handle_result = can_handle_result
        self.calls = 0
        self.last_event = None

    def can_handle(self, event) -> bool:
        self.last_event = event
        return self.can_handle_result

    def handle(self, event):
        self.calls += 1
        return {
            "statusCode": 200,
            "headers": {},
            "multiValueHeaders": {},
            "body": "",
            "isBase64Encoded": False,
        }


class DummyPolicyHandler:
    def __init__(self, can_handle_result: bool) -> None:
        self.can_handle_result = can_handle_result
        self.calls = 0

    def can_handle(self, event) -> bool:
        return self.can_handle_result

    def handle(self, event) -> None:
        self.calls += 1


def test_api_gateway_event_handler_routes_and_normalizes_resource() -> None:
    jwt_handler = DummyJwtHandler()
    cors_handler = DummyCorsHandler()
    rest_handler = DummyRestHandler(can_handle_result=True)
    handler = ApiGatewayEventHandler(
        handlers=[rest_handler],
        jwt_token_handler=jwt_handler,
        cors_handler=cors_handler,
    )

    response = handler.handle(
        {
            "httpMethod": "GET",
            "path": "/items/123",
            "pathParameters": {"id": "123"},
            "headers": {},
        }
    )

    assert jwt_handler.calls == 1
    assert cors_handler.calls == 1
    assert rest_handler.calls == 1
    assert rest_handler.last_event["resource"] == "/items/{id}"
    assert response["statusCode"] == 200


def test_api_gateway_event_handler_skips_jwt_for_options() -> None:
    jwt_handler = DummyJwtHandler()
    cors_handler = DummyCorsHandler()
    rest_handler = DummyRestHandler(can_handle_result=True)
    handler = ApiGatewayEventHandler(
        handlers=[rest_handler],
        jwt_token_handler=jwt_handler,
        cors_handler=cors_handler,
    )

    handler.handle({"httpMethod": "OPTIONS", "resource": "/items", "headers": {}})

    assert jwt_handler.calls == 0


def test_api_gateway_event_handler_returns_not_found_when_no_rest_handler_matches() -> None:
    jwt_handler = DummyJwtHandler()
    cors_handler = DummyCorsHandler()
    rest_handler = DummyRestHandler(can_handle_result=False)
    handler = ApiGatewayEventHandler(
        handlers=[rest_handler],
        jwt_token_handler=jwt_handler,
        cors_handler=cors_handler,
    )

    response = handler.handle({"httpMethod": "GET", "resource": "/missing", "headers": {}})

    assert response["statusCode"] == 404


def test_eventbridge_event_handler_routes_to_matching_policy_handler_and_sets_system_principal() -> None:
    ignored = DummyPolicyHandler(can_handle_result=False)
    matched = DummyPolicyHandler(can_handle_result=True)
    handler = EventBridgeEventHandler(handlers=[ignored, matched])

    handler.handle({"detail-type": "sample", "source": "tests"})

    assert ignored.calls == 0
    assert matched.calls == 1
    assert principal().name == "system"

