"""Controller for provider payload optimization and forwarding."""

import logging
import hashlib
import json
from typing import Dict, Any
import httpx
from fastapi import HTTPException

from app.core.exceptions import ValidationError, APIException
from app.services.routing.route_optimizer import RouteOptimizer
from app.services import cache

logger = logging.getLogger(__name__)


class RouteController:
    """Controller for optimizing provider payloads and forwarding upstream."""
    
    def __init__(self):
        self.route_optimizer = RouteOptimizer()
    
    def _hash_key(self, prefix: str, payload: Dict[str, Any]) -> str:
        """Create a stable cache key from a dict payload."""
        # ensure deterministic json by sorting keys
        serialized = json.dumps(payload, sort_keys=True, separators=(",", ":"))
        digest = hashlib.sha256(serialized.encode("utf-8")).hexdigest()
        return f"routes:{prefix}:{digest}"
    
    async def optimize_and_forward_provider_payload(self, orders: list[dict], forward_url: str) -> dict:
        """Optimize provider payload and return it (forwarding paused).
        
        - Input: list of provider orders (dicts)
        - Output: {code, details, message, status} where details is the optimized array
        """
        try:
            if not isinstance(orders, list) or not orders:
                raise ValidationError("Orders array is required", field="body")

            # Create a cache key from the orders payload
            cache_key = self._hash_key("provider_payload", {"orders": orders})
            
            # Check cache
            cached_result = cache.get_json(cache_key)
            if cached_result:
                logger.info(f"Cache hit for key: {cache_key}")
                return cached_result

            optimized = await self.route_optimizer.optimize_provider_payload(orders)

            # Debug sample of optimized payload (first 3 items, select keys)
            try:
                sample = [
                    {
                        k: item.get(k)
                        for k in ("orderheaderid", "orderid", "deliverycustomerid", "step", "previouskms", "cumulativekms", "eta")
                    }
                    for item in optimized[:3]
                ]
                logger.debug(f"Optimized payload sample: {sample}")
                trace = [
                    {
                        "orderid": item.get("orderid"),
                        "step": item.get("step"),
                        "prev": item.get("previouskms"),
                        "cum": item.get("cumulativekms"),
                    }
                    for item in optimized
                ]
                logger.debug(f"Optimized order trace: {trace}")
            except Exception:
                logger.debug("Optimized payload sample logging failed")

            # Forwarding paused: return optimized payload directly
            result = {
                "code": 200,
                "details": optimized,
                "message": "Success",
                "status": True,
            }
            
            # Store in cache
            try:
                cache.set_json(cache_key, result)
            except Exception as e:
                logger.warning(f"Failed to cache optimization result: {e}")

            return result
        except ValidationError:
            raise
        except httpx.HTTPStatusError as e:
            status_code = e.response.status_code
            body_text = e.response.text
            logger.error(f"Forwarding failed: {status_code} - {body_text}")
            # Surface upstream details to the client for faster debugging
            raise APIException(
                status_code=502,
                message=f"Upstream service error (status {status_code}): {body_text}",
                code="UPSTREAM_ERROR"
            )
        except Exception as e:
            logger.error(f"Error optimizing/forwarding provider payload: {e}", exc_info=True)
            raise APIException(status_code=500, message="Internal server error", code="INTERNAL_ERROR")
# Batch routes removed - use single-route optimization for each pickup location