"""AgentBill Signals Resource — REST API path for signal CRUD.

Standalone signal creation/listing via the existing api-ingest and list-signals
endpoints. This is for users who don't use OTEL tracing context.

v8.1.0: Created as part of Signals Revamp Phase 2.
"""
from typing import Any, Dict, List, Optional
import httpx

from ..types import Signal, BulkResult


class SignalsResource:
    """REST API resource for signal CRUD operations.
    
    Provides a REST-based alternative to the OTEL-based signal() function.
    Uses the existing api-ingest endpoint which accepts flat JSON and
    maps it to the unified OTEL format server-side.
    
    Example:
        >>> from agentbill import AgentBill
        >>> client = AgentBill.init({"api_key": "agb_..."})
        >>> 
        >>> # Create a signal via REST
        >>> result = client.signals.create({
        ...     "event_name": "purchase",
        ...     "revenue": 99.99,
        ...     "customer_id": "cust-123",
        ... })
        >>> 
        >>> # Create multiple signals
        >>> result = client.signals.create_many([
        ...     {"event_name": "page_view", "customer_id": "cust-123"},
        ...     {"event_name": "signup", "revenue": 0, "customer_id": "cust-456"},
        ... ])
        >>> 
        >>> # List signals
        >>> signals = client.signals.list(limit=20)
    """
    
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.base_url = config.get("base_url", "https://api.agentbill.io")
        self.api_key = config["api_key"]
        self.debug = config.get("debug", False)
    
    def _get_headers(self) -> Dict[str, str]:
        return {
            "Content-Type": "application/json",
            "X-API-Key": self.api_key,
        }
    
    def create(self, signal: Signal) -> Dict[str, Any]:
        """Create a signal via REST API (standalone, no trace context needed).
        
        Uses the api-ingest endpoint which accepts flat JSON and maps
        top-level fields (event_name, model, provider, revenue, etc.)
        to the unified OTEL format server-side.
        
        Args:
            signal: Signal payload (TypedDict with event_name required)
            
        Returns:
            Dict with success status and signal metadata
            
        Example:
            >>> result = client.signals.create({
            ...     "event_name": "ai_completion",
            ...     "model": "gpt-4",
            ...     "input_tokens": 150,
            ...     "output_tokens": 50,
            ...     "customer_id": "cust-123",
            ... })
        """
        url = f"{self.base_url}/functions/v1/api-ingest"
        
        # Map Signal TypedDict fields to api-ingest payload format
        payload: Dict[str, Any] = dict(signal)
        
        # Inject customer/agent from config if not in signal
        if "customer_id" not in payload and self.config.get("customer_id"):
            payload["customer_id"] = self.config["customer_id"]
        if "customer_id" not in payload and self.config.get("customer_external_id"):
            payload["customer_external_id"] = self.config["customer_external_id"]
        if self.config.get("agent_id") and "agent_id" not in payload:
            payload["agent_id"] = self.config["agent_id"]
        if self.config.get("agent_external_id") and "agent_external_id" not in payload:
            payload["agent_external_id"] = self.config["agent_external_id"]
        
        try:
            with httpx.Client(timeout=10) as http_client:
                response = http_client.post(url, json=payload, headers=self._get_headers())
                
                result = {}
                try:
                    result = response.json()
                except Exception:
                    pass
                
                is_success = response.status_code in (200, 201) and result.get("success", True)
                
                if self.debug:
                    event = payload.get("event_name", "unknown")
                    if is_success:
                        print(f"[AgentBill] ✓ Signal '{event}' created via REST")
                    else:
                        print(f"[AgentBill] ⚠️ Signal '{event}' creation failed: {result.get('error', response.text)}")
                
                return {
                    "success": is_success,
                    "status_code": response.status_code,
                    **result,
                }
        except Exception as e:
            if self.debug:
                print(f"[AgentBill] ⚠️ Signal creation error: {e}")
            return {"success": False, "error": str(e)}
    
    def create_many(self, signals: List[Signal]) -> BulkResult:
        """Create multiple signals via REST API.
        
        Sends each signal individually to api-ingest. For high-throughput
        bulk ingestion, prefer record_bulk() which uses the OTEL path.
        
        Args:
            signals: List of Signal payloads
            
        Returns:
            BulkResult with processed count and per-signal results
            
        Example:
            >>> result = client.signals.create_many([
            ...     {"event_name": "page_view", "customer_id": "cust-1"},
            ...     {"event_name": "purchase", "revenue": 49.99, "customer_id": "cust-2"},
            ... ])
            >>> print(f"Processed: {result['processed']}/{len(signals)}")
        """
        results: List[Dict[str, Any]] = []
        processed = 0
        
        for sig in signals:
            result = self.create(sig)
            results.append(result)
            if result.get("success"):
                processed += 1
        
        return {
            "success": processed == len(signals),
            "processed": processed,
            "results": results,
            "error": None if processed == len(signals) else f"{len(signals) - processed} signal(s) failed",
        }
    
    def list(
        self,
        *,
        limit: int = 50,
        offset: int = 0,
        customer_id: Optional[str] = None,
        agent_id: Optional[str] = None,
        event_name: Optional[str] = None,
        start_date: Optional[str] = None,
        end_date: Optional[str] = None,
    ) -> Dict[str, Any]:
        """List signals via REST API.
        
        Uses the list-signals endpoint which maps otel_spans data back
        into a signal-like shape for backward compatibility.
        
        Args:
            limit: Max signals to return (default 50)
            offset: Pagination offset
            customer_id: Filter by customer
            agent_id: Filter by agent
            event_name: Filter by event name
            start_date: ISO date string for range start
            end_date: ISO date string for range end
            
        Returns:
            Dict with signals list and pagination metadata
            
        Example:
            >>> signals = client.signals.list(limit=10, customer_id="cust-123")
            >>> for s in signals.get("data", []):
            ...     print(s["event_name"], s.get("revenue"))
        """
        url = f"{self.base_url}/functions/v1/list-signals"
        
        params: Dict[str, Any] = {
            "limit": limit,
            "offset": offset,
        }
        if customer_id:
            params["customer_id"] = customer_id
        if agent_id:
            params["agent_id"] = agent_id
        if event_name:
            params["event_name"] = event_name
        if start_date:
            params["start_date"] = start_date
        if end_date:
            params["end_date"] = end_date
        
        try:
            with httpx.Client(timeout=10) as http_client:
                response = http_client.get(url, params=params, headers=self._get_headers())
                
                result = {}
                try:
                    result = response.json()
                except Exception:
                    pass
                
                if self.debug:
                    count = len(result.get("data", []))
                    print(f"[AgentBill] ✓ Listed {count} signals")
                
                return {
                    "success": response.status_code == 200,
                    "status_code": response.status_code,
                    **result,
                }
        except Exception as e:
            if self.debug:
                print(f"[AgentBill] ⚠️ Signal list error: {e}")
            return {"success": False, "error": str(e), "data": []}
