from blocks_control_sdk.activity_providers.base import AgentActivityProvider
from blocks_control_sdk.blocks_events.context import BLOCKS_EVENT__PROVIDER, BLOCKS_EVENT__GITHUB__TYPE
from blocks_control_sdk.control.agent_base import LLM, NotifyMessageArgs, NotifyCompleteArgs, NotifyToolCallArgs
from blocks_control_sdk.tools.blocks import get_task_header, get_task_message_with_footer
from blocks_control_sdk.tools.github import (
    create_github_pr_comment,
    create_github_issue_comment,
    create_github_pr_respond_to_comment_on_file,
    update_github_issue_or_pr_comment_with_header,
    update_github_pr_comment_on_file_with_header,
    update_message__github,
)
from blocks_control_sdk.utils import patch_blocks_runtime_config, get_blocks_runtime_config


class GitHubActivityProvider(AgentActivityProvider):
    def setup(self, input: dict, llm_provider: LLM) -> None:
        super().setup(input, llm_provider)
        if self.trigger_alias == "github.pull_request_comment":
            self._setup_pull_request(input, llm_provider)
        elif self.trigger_alias == "github.issue_comment":
            self._setup_issue(input, llm_provider)
        elif self.trigger_alias == "github.pull_request_review_comment":
            self._setup_review_comment(input, llm_provider)

    def _setup_pull_request(self, input: dict, llm_provider: LLM) -> None:
        pull_request = input.get("pull_request", {})
        pull_request_number = pull_request.get("number")

        issue_header = get_task_header(is_github=True)
        initial_github_comment_id = input.get("$blocks.provider.comment_id")

        github_comment_id = initial_github_comment_id
        if not initial_github_comment_id:
            github_comment_id = create_github_pr_comment(pull_request_number, body=issue_header)

        patch_blocks_runtime_config({
            "event_provider": BLOCKS_EVENT__PROVIDER.GITHUB.value,
            "event_type": BLOCKS_EVENT__GITHUB__TYPE.PULL_REQUEST.value,
            "llm_provider": llm_provider.value,
            "metadata": {
                "comment_id": github_comment_id,
            }
        })

    def _setup_issue(self, input: dict, llm_provider: LLM) -> None:
        issue = input.get("issue", {})
        issue_number = issue.get("number")

        issue_header = get_task_header(is_github=True)
        initial_github_comment_id = input.get("$blocks.provider.comment_id")

        github_comment_id = initial_github_comment_id
        if not initial_github_comment_id:
             github_comment_id = create_github_issue_comment(issue_number, body=issue_header)

        patch_blocks_runtime_config({
            "event_provider": BLOCKS_EVENT__PROVIDER.GITHUB.value,
            "event_type": BLOCKS_EVENT__GITHUB__TYPE.ISSUE.value,
            "llm_provider": llm_provider.value,
            "metadata": {
                "comment_id": github_comment_id,
            }
        })

    def _setup_review_comment(self, input: dict, llm_provider: LLM) -> None:
        pull_request = input.get("pull_request", {})
        pull_request_number = pull_request.get("number")
        latest_comment = input.get("new_comment", {})

        reply_to_id = input.get("$blocks.trigger.subject_id") or latest_comment.get("in_reply_to_id") or latest_comment.get("id")

        issue_header = get_task_header(is_github=True)
        initial_github_comment_id = input.get("$blocks.provider.comment_id")

        github_comment_id = initial_github_comment_id
        if not initial_github_comment_id:
            github_comment_id = create_github_pr_respond_to_comment_on_file(body=issue_header, pull_request_number=pull_request_number, reply_to_id=reply_to_id)

        patch_blocks_runtime_config({
            "event_provider": BLOCKS_EVENT__PROVIDER.GITHUB.value,
            "event_type": BLOCKS_EVENT__GITHUB__TYPE.PULL_REQUEST_REVIEW_COMMENT.value,
            "llm_provider": llm_provider.value,
            "metadata": {
                "comment_id": github_comment_id,
            }
        })

    def on_message(self, notification: NotifyMessageArgs) -> None:
        summary = self._prepare_progress_summary(notification)
        if summary:
            blocks_runtime_config = get_blocks_runtime_config()
            comment_id = blocks_runtime_config.get("metadata", {}).get("comment_id")
            if comment_id:
                if self.trigger_alias != "github.pull_request_review_comment":
                    update_github_issue_or_pr_comment_with_header(comment_id, summary)
                else:
                    update_github_pr_comment_on_file_with_header(comment_id, summary)

    def on_complete(self, notification: NotifyCompleteArgs) -> None:
        message = notification.last_message
        if message:
            final_message_github = get_task_message_with_footer(message, is_github=True)
            update_message__github(final_message_github, include_user_message=True)

    def on_tool_call(self, notification: NotifyToolCallArgs) -> None:
        pass

    def check(self, messages: list) -> None:
        if self.trigger_alias != "github.pull_request_review_comment":
            return
        user_messages = self._get_user_messages(messages)
        if not user_messages:
            return

        pull_request = self.input.get("pull_request", {})
        pull_request_number = pull_request.get("number")
        latest_comment = self.input.get("new_comment", {})
        reply_to_id = latest_comment.get("reply_to_id") or latest_comment.get("id")

        issue_header = get_task_header(is_github=True)
        new_comment_id = create_github_pr_respond_to_comment_on_file(
            body=issue_header,
            pull_request_number=pull_request_number,
            reply_to_id=reply_to_id
        )

        patch_blocks_runtime_config({"metadata": {"comment_id": new_comment_id}}, deep_patch=True)
