import os
from typing import List

from blocks_control_sdk.activity_providers.base import AgentActivityProvider
from blocks_control_sdk.activity_providers.blocks_provider import BlocksActivityProvider
from blocks_control_sdk.activity_providers.github_provider import GitHubActivityProvider
from blocks_control_sdk.activity_providers.linear_provider import LinearActivityProvider
from blocks_control_sdk.activity_providers.gitlab_provider import GitLabActivityProvider
from blocks_control_sdk.activity_providers.slack_provider import SlackActivityProvider
from blocks_control_sdk.activity_providers.webhook_provider import WebhookActivityProvider
from blocks_control_sdk.activity_providers.sandbox_provider import SandboxActivityProvider

TRIGGER_ALIAS_TO_PROVIDER = {
    "github.issue_comment": GitHubActivityProvider,
    "github.pull_request_comment": GitHubActivityProvider,
    "github.pull_request_review_comment": GitHubActivityProvider,
    "linear.issue_comment": LinearActivityProvider,
    "linear.assign": LinearActivityProvider,
    "gitlab.issue_comment": GitLabActivityProvider,
    "gitlab.merge_request_comment": GitLabActivityProvider,
    "webhook": WebhookActivityProvider,
    "slack.mention": SlackActivityProvider,
}


class AgentActivity:
    """Facade: resolves providers, runs setup, registers callbacks."""

    def __init__(self, providers: List[AgentActivityProvider]):
        self.providers = providers

    @staticmethod
    def resolve(input: dict, llm_provider, trigger_alias: str = None) -> 'AgentActivity':
        """Resolve providers and run setup. Prompt is built separately by the caller."""
        if trigger_alias is None:
            trigger_alias = os.getenv("BLOCKS_TRIGGER_ALIAS")

        # Resolve & instantiate providers
        providers: List[AgentActivityProvider] = [
            BlocksActivityProvider(trigger_alias),
            SandboxActivityProvider(trigger_alias),
        ]
        provider_class = TRIGGER_ALIAS_TO_PROVIDER.get(trigger_alias)
        if provider_class:
            providers.append(provider_class(trigger_alias))

        # Run setup (side effects: create comments, patch runtime config)
        for provider in providers:
            provider.setup(input, llm_provider)

        return AgentActivity(providers=providers)

    def check(self, messages: list) -> None:
        """Run check() on all providers. May raise SandboxPausingError."""
        for provider in self.providers:
            provider.check(messages)

    def register(self, agent) -> None:
        """Register all provider notification callbacks on the agent."""
        for provider in self.providers:
            agent.register_notification(agent.notifications.NOTIFY_MESSAGE_V2, provider.on_message)
            agent.register_notification(agent.notifications.NOTIFY_COMPLETE_V2, provider.on_complete)
            agent.register_notification(agent.notifications.NOTIFY_TOOL_CALL_V2, provider.on_tool_call)
            agent.register_notification(agent.notifications.NOTIFY_START_V2, provider.on_start)
            agent.register_notification(agent.notifications.NOTIFY_RESUME_V2, provider.on_resume)
            agent.register_notification(agent.notifications.NOTIFY_INTERRUPT_V2, provider.on_interrupt)

        # Internal message handler for cross-cutting concerns (child PID registration, hot reload)
        from blocks_control_sdk.control.agent_base import NotifyInternalMessageArgs

        def _on_internal_message(notification: NotifyInternalMessageArgs):
            payload = notification.payload
            action = payload.get("action")

            if action == "register_child_pid":
                pid = payload.get("pid")
                if pid:
                    print(f"[Entrypoint] Registering child PID from tool: {pid}")
                    agent.register_child_pid(pid)
            elif action == "hot_reload":
                print(f"[Agent Hot Reload] Hot reload requested")
                agent.hot_reload()
                print(f"[Agent Hot Reload] Hot reload completed successfully")

        agent.register_notification(agent.notifications.NOTIFY_INTERNAL_MESSAGE, _on_internal_message)
