# ============================================================================
# RATIONALBLOKS MCP - LOGICBLOK CLIENT
# ============================================================================
# Copyright 2026 RationalBloks. All Rights Reserved.
#
# HTTP client for LogicBlok API (businessblok.rationalbloks.com)
# Handles all API communication for backend tools.
# ============================================================================

import httpx
import json
from typing import Any

# Public API
__all__ = ["LogicBlokClient"]


class LogicBlokClient:
    """HTTP client for LogicBlok API.
    
    Provides:
    - Authentication via Bearer token
    - All backend API operations
    - Proper error handling
    """
    
    BASE_URL = "https://businessblok.rationalbloks.com"
    
    def __init__(self, api_key: str) -> None:
        """Initialize client with API key.
        
        Args:
            api_key: RationalBloks API key (rb_sk_...)
        """
        self.api_key = api_key
        self._client = httpx.AsyncClient(
            base_url=self.BASE_URL,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30.0,
        )
    
    async def close(self) -> None:
        """Close the HTTP client."""
        await self._client.aclose()
    
    async def __aenter__(self) -> "LogicBlokClient":
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
        await self.close()
    
    # ========================================================================
    # READ OPERATIONS
    # ========================================================================
    
    async def list_projects(self) -> list[dict]:
        """List all projects for the authenticated user."""
        response = await self._client.get("/mcp/projects")
        response.raise_for_status()
        return response.json()
    
    async def get_project(self, project_id: str) -> dict:
        """Get details of a specific project."""
        response = await self._client.get(f"/mcp/projects/{project_id}")
        response.raise_for_status()
        return response.json()
    
    async def get_project_info(self, project_id: str) -> dict:
        """Get detailed project info including deployment status."""
        response = await self._client.get(f"/mcp/projects/{project_id}/info")
        response.raise_for_status()
        return response.json()
    
    async def get_schema(self, project_id: str) -> dict:
        """Get the current schema for a project."""
        response = await self._client.get(f"/mcp/projects/{project_id}/schema")
        response.raise_for_status()
        return response.json()
    
    async def get_schema_at_version(self, project_id: str, version: str) -> dict:
        """Get schema at a specific version/commit."""
        response = await self._client.get(
            f"/mcp/projects/{project_id}/schema/version/{version}"
        )
        response.raise_for_status()
        return response.json()
    
    async def get_version_history(self, project_id: str) -> list[dict]:
        """Get deployment history for a project."""
        response = await self._client.get(f"/mcp/projects/{project_id}/versions")
        response.raise_for_status()
        return response.json()
    
    async def get_job_status(self, job_id: str) -> dict:
        """Check the status of a deployment job."""
        response = await self._client.get(f"/mcp/jobs/{job_id}")
        response.raise_for_status()
        return response.json()
    
    async def get_project_usage(self, project_id: str) -> dict:
        """Get resource usage metrics for a project."""
        response = await self._client.get(f"/mcp/projects/{project_id}/usage")
        response.raise_for_status()
        return response.json()
    
    async def get_user_info(self) -> dict:
        """Get information about the authenticated user."""
        response = await self._client.get("/mcp/user")
        response.raise_for_status()
        return response.json()
    
    async def get_subscription_status(self) -> dict:
        """Get subscription tier, limits, and usage."""
        response = await self._client.get("/mcp/subscription")
        response.raise_for_status()
        return response.json()
    
    async def get_template_schemas(self) -> dict:
        """Get pre-built template schemas for common use cases."""
        response = await self._client.get("/mcp/templates")
        response.raise_for_status()
        return response.json()
    
    # ========================================================================
    # WRITE OPERATIONS
    # ========================================================================
    
    async def create_project(
        self,
        name: str,
        schema: dict,
        description: str | None = None,
    ) -> dict:
        """Create a new project from a JSON schema.
        
        Args:
            name: Project name
            schema: JSON schema in FLAT format
            description: Optional project description
        
        Returns:
            Project details with job_id for deployment tracking
        """
        payload = {"name": name, "schema": schema}
        if description:
            payload["description"] = description
        
        response = await self._client.post("/mcp/projects", json=payload)
        response.raise_for_status()
        return response.json()
    
    async def update_schema(self, project_id: str, schema: dict) -> dict:
        """Update a project's schema (does NOT deploy).
        
        Args:
            project_id: Project UUID
            schema: New JSON schema in FLAT format
        
        Returns:
            Updated project details
        """
        response = await self._client.put(
            f"/mcp/projects/{project_id}/schema",
            json={"schema": schema},
        )
        response.raise_for_status()
        return response.json()
    
    async def deploy_staging(self, project_id: str) -> dict:
        """Deploy a project to staging environment.
        
        Args:
            project_id: Project UUID
        
        Returns:
            Deployment job details
        """
        response = await self._client.post(
            f"/mcp/projects/{project_id}/deploy/staging"
        )
        response.raise_for_status()
        return response.json()
    
    async def deploy_production(self, project_id: str) -> dict:
        """Promote staging to production (requires paid plan).
        
        Args:
            project_id: Project UUID
        
        Returns:
            Deployment job details
        """
        response = await self._client.post(
            f"/mcp/projects/{project_id}/deploy/production"
        )
        response.raise_for_status()
        return response.json()
    
    async def delete_project(self, project_id: str) -> dict:
        """Delete a project and all associated resources.
        
        Args:
            project_id: Project UUID
        
        Returns:
            Deletion confirmation
        """
        response = await self._client.delete(f"/mcp/projects/{project_id}")
        response.raise_for_status()
        return response.json()
    
    async def rollback_project(
        self,
        project_id: str,
        version: str,
        environment: str = "staging",
    ) -> dict:
        """Rollback a project to a previous version.
        
        Args:
            project_id: Project UUID
            version: Commit SHA to rollback to
            environment: staging or production
        
        Returns:
            Rollback job details
        """
        response = await self._client.post(
            f"/mcp/projects/{project_id}/rollback",
            json={"version": version, "environment": environment},
        )
        response.raise_for_status()
        return response.json()
    
    async def rename_project(self, project_id: str, name: str) -> dict:
        """Rename a project (display name only).
        
        Args:
            project_id: Project UUID
            name: New display name
        
        Returns:
            Updated project details
        """
        response = await self._client.patch(
            f"/mcp/projects/{project_id}",
            json={"name": name},
        )
        response.raise_for_status()
        return response.json()
