"""
EchoStash Python Helper

A lightweight client for the EchoStash API.
No external dependencies - uses Python's built-in urllib.

Usage:
    from echostash import EchoStashClient
    
    client = EchoStashClient(
        api_key="sk_your_api_key",
        base_url="https://gra-echostash-be-prod.up.railway.app"
    )
    
    # Get a prompt
    prompt = client.get_prompt(123)
    print(prompt["content"])
    
    # Get a specific version
    version = client.get_version(123, version_no=2)
    print(version["content"])
    
    # Render a prompt with variables
    rendered = client.render_prompt(123, variables={"name": "World"})
    print(rendered["content"])
"""

import json
import urllib.request
import urllib.error
from typing import Dict, Any, Optional


class EchoStashError(Exception):
    """Base exception for EchoStash API errors."""
    
    def __init__(self, message: str, status: int, response: Optional[Dict[str, Any]] = None):
        super().__init__(message)
        self.status = status
        self.response = response


class EchoStashClient:
    """
    A lightweight client for the EchoStash API.
    
    Args:
        api_key: Your EchoStash API key (starts with sk_)
        base_url: The base URL for the API
    """
    
    def __init__(self, api_key: str, base_url: str = "https://gra-echostash-be-prod.up.railway.app"):
        if not api_key:
            raise ValueError("API key is required")
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")

    def _request(self, method: str, path: str, body: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """Make an HTTP request to the API."""
        url = f"{self.base_url}{path}"
        
        headers = {
            "X-API-KEY": self.api_key,
            "Content-Type": "application/json",
        }
        
        data = json.dumps(body).encode("utf-8") if body else None
        req = urllib.request.Request(url, data=data, headers=headers, method=method)
        
        try:
            with urllib.request.urlopen(req) as response:
                return json.loads(response.read().decode("utf-8"))
        except urllib.error.HTTPError as e:
            error_body = None
            try:
                error_body = json.loads(e.read().decode("utf-8"))
            except Exception:
                pass
            raise EchoStashError(
                message=error_body.get("error", str(e)) if error_body else str(e),
                status=e.code,
                response=error_body
            )

    def get_prompt(self, prompt_id: int) -> Dict[str, Any]:
        """
        Fetch a prompt by its ID.
        
        Args:
            prompt_id: The ID of the prompt to fetch
            
        Returns:
            A dictionary containing the prompt data
        """
        return self._request("GET", f"/api/sdk/prompts/{prompt_id}")

    def get_version(self, prompt_id: int, version_no: int) -> Dict[str, Any]:
        """
        Fetch a specific version of a prompt.
        
        Args:
            prompt_id: The ID of the prompt
            version_no: The version number to fetch
            
        Returns:
            A dictionary containing the version data
        """
        return self._request("GET", f"/api/sdk/prompts/{prompt_id}/versions/{version_no}")

    def render_prompt(
        self,
        prompt_id: int,
        variables: Optional[Dict[str, str]] = None,
        version: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        Render a prompt with variable substitution.
        
        Args:
            prompt_id: The ID of the prompt to render
            variables: A dictionary of variables to substitute
            version: Optional version number or "latest" for unpublished
            
        Returns:
            A dictionary containing the rendered content
        """
        body: Dict[str, Any] = {}
        if variables:
            body["variables"] = variables
        if version:
            body["version"] = version
        
        return self._request("POST", f"/api/sdk/prompts/{prompt_id}/render", body)
