from __future__ import annotations

from typing import Any

from universal_mcp.agentr.client import AgentrClient
from universal_mcp.agentr.types import AgentResponse, TemplateResponse


class AgentBuilderRegistry:
    """
    HTTP client wrapper for Agent Builder operations.
    """

    def __init__(
        self,
        *,
        client: AgentrClient,
        default_agent_id: str | None = None,
        default_template_id: str | None = None,
    ):
        if not client:
            raise ValueError("AgentBuilderRegistry requires a valid AgentrClient")
        self.client = client
        self.default_agent_id = default_agent_id
        self.default_template_id = default_template_id

    async def get_agent(self, agent_id: str | None = None) -> AgentResponse | TemplateResponse | None:
        # agent_id takes precedence, then default_agent_id, else template
        use_agent_id = agent_id or self.default_agent_id
        if use_agent_id:
            return await self.client.get_agent(agent_id=str(use_agent_id))
        if self.default_template_id:
            return await self.client.get_template(template_id=str(self.default_template_id))
        return None

    async def create_agent(
        self,
        *,
        name: str | None = None,
        description: str | None = None,
        instructions: dict[str, Any] | None = None,
        tools: dict[str, list[str]] | None = None,
        html: str | None = None,
        details: str | None = None,
    ) -> AgentResponse:
        return await self.client.create_agent(
            name=name,
            description=description,
            instructions=instructions,
            tools=tools,
            html=html,
            details=details,
        )

    async def update_agent(
        self,
        *,
        agent_id: str | None = None,
        name: str | None = None,
        description: str | None = None,
        instructions: dict[str, Any] | None = None,
        tools: dict[str, list[str]] | None = None,
        html: str | None = None,
        details: str | None = None,
    ) -> AgentResponse:
        use_agent_id = agent_id or self.default_agent_id
        if not use_agent_id:
            raise ValueError("agent_id not provided and no default_agent_id set")

        return await self.client.update_agent(
            agent_id=str(use_agent_id),
            name=name,
            description=description,
            instructions=instructions,
            tools=tools,
            html=html,
            details=details,
        )

    async def upsert_agent(
        self,
        *,
        name: str | None = None,
        description: str | None = None,
        instructions: dict[str, Any] | None = None,
        tools: dict[str, list[str]] | None = None,
        cron: str | None = None,
        html: str | None = None,
        details: str | None = None,
    ) -> tuple[AgentResponse, bool]:
        if self.default_agent_id:
            res = await self.update_agent(
                agent_id=self.default_agent_id,
                name=name,
                description=description,
                instructions=instructions,
                tools=tools,
                html=html,
                details=details,
            )
        else:
            res = await self.create_agent(
                name=name,
                description=description,
                instructions=instructions,
                tools=tools,
                html=html,
                details=details,
            )

        if cron:
            await self.schedule_agent(cron=cron, agent_id=str(res.id))

        return res, bool(self.default_agent_id)

    async def schedule_agent(self, cron: str, agent_id: str | None = None) -> None:
        use_agent_id = agent_id or self.default_agent_id
        if not use_agent_id:
            raise ValueError("agent_id not provided and no default_agent_id set")

        jobs = await self.client.list_jobs(agent_id=str(use_agent_id))
        if jobs:
            # Update existing job
            await self.client.update_job(
                job_id=jobs[0]["id"],
                cron=cron,
                agent_id=str(use_agent_id),
            )
        else:
            # Create new job
            await self.client.create_job(
                task_name="invoke_agent",
                cron=cron,
                agent_id=str(use_agent_id),
                params={
                    "agent_id": str(use_agent_id),
                    "user_id": self.client.user_id.split(":")[0],
                    "org_id": self.client.org_id,
                },
            )
