"""AgentBill Orders Resource - CRUD operations with line items via unified HTTP client"""

from typing import Any, Dict, List, Optional
from ..http_client import AgentBillHTTPClient
from ..raw_response import WithRawResponseMixin
from ..logger import get_logger

_log = get_logger("orders")


class OrdersResource(WithRawResponseMixin):
    """Orders resource for CRUD operations via unified HTTP client.

    IMPORTANT: At least one agent must be associated with an order via
    agent_ids or agent_external_ids.
    """

    _resource_path = "/functions/v1/api-orders"

    def __init__(self, config: Dict[str, Any], http_client: "AgentBillHTTPClient" = None):
        self.config = config
        self.debug = config.get("debug", False)
        self._http = http_client

    def list(
        self,
        account_id: Optional[str] = None,
        status: Optional[str] = None,
        limit: int = 50,
        offset: int = 0,
        search: Optional[str] = None,
    ) -> Dict[str, Any]:
        """List orders with pagination and filtering."""
        params = {"limit": str(limit), "offset": str(offset)}
        if search:
            params["search"] = search
        if account_id:
            params["account_id"] = account_id
        if status:
            params["status"] = status

        resp = self._http.get(self._resource_path, params=params)
        return resp.data

    def create(
        self,
        account_id: str,
        name: str,
        agent_ids: Optional[List[str]] = None,
        agent_external_ids: Optional[List[str]] = None,
        external_id: Optional[str] = None,
        account_external_id: Optional[str] = None,
        billing_contact_id: Optional[str] = None,
        billing_contact_external_id: Optional[str] = None,
        start_date: Optional[str] = None,
        end_date: Optional[str] = None,
        status: Optional[str] = None,
        currency: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """Create a new order. At least one agent required."""
        if not agent_ids and not agent_external_ids:
            raise ValueError(
                "At least one agent must be specified via agent_ids or agent_external_ids. "
                "Orders cannot be created without agent association for billing attribution."
            )

        payload: Dict[str, Any] = {"account_id": account_id, "name": name}
        for key, val in {
            "agent_ids": agent_ids, "agent_external_ids": agent_external_ids,
            "external_id": external_id, "account_external_id": account_external_id,
            "billing_contact_id": billing_contact_id,
            "billing_contact_external_id": billing_contact_external_id,
            "start_date": start_date, "end_date": end_date,
            "status": status, "currency": currency, "metadata": metadata,
        }.items():
            if val is not None:
                payload[key] = val

        _log.debug("Creating order: %s", name)
        resp = self._http.post(self._resource_path, json=payload)
        return resp.data

    def get(self, order_id: str, by_external_id: bool = False) -> Dict[str, Any]:
        """Get an order by ID or external_id (includes line items)."""
        params = {}
        if by_external_id:
            params["external_id"] = order_id
        else:
            params["id"] = order_id

        resp = self._http.get(self._resource_path, params=params)
        return resp.data

    def update(
        self,
        order_id: str,
        name: Optional[str] = None,
        billing_contact_id: Optional[str] = None,
        start_date: Optional[str] = None,
        end_date: Optional[str] = None,
        status: Optional[str] = None,
        currency: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """Update an order."""
        payload: Dict[str, Any] = {"id": order_id}
        for key, val in {
            "name": name, "billing_contact_id": billing_contact_id,
            "start_date": start_date, "end_date": end_date,
            "status": status, "currency": currency, "metadata": metadata,
        }.items():
            if val is not None:
                payload[key] = val

        resp = self._http.patch(self._resource_path, json=payload)
        return resp.data

    def delete(self, order_id: str) -> None:
        """Delete an order and its line items."""
        self._http.request("DELETE", self._resource_path, json={"id": order_id})

    def list_line_items(self, order_id: str) -> Dict[str, Any]:
        """List line items for an order."""
        resp = self._http.get(self._resource_path, params={"order_id": order_id, "action": "line-items"})
        return resp.data

    def add_line_item(
        self,
        order_id: str,
        description: str,
        quantity: float,
        unit_price: float,
        product_id: Optional[str] = None,
        product_name: Optional[str] = None,
        product_sku: Optional[str] = None,
        usage_metric: Optional[str] = None,
        usage_quantity: Optional[float] = None,
        discount_type: Optional[str] = None,
        discount_value: Optional[float] = None,
        tax_rate: Optional[float] = None,
        notes: Optional[str] = None,
        sort_order: Optional[int] = None,
        agent_id: Optional[str] = None,
        item_type: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """Add a line item to an order."""
        payload: Dict[str, Any] = {
            "order_id": order_id,
            "description": description,
            "quantity": quantity,
            "unit_price": unit_price,
        }
        for key, val in {
            "product_id": product_id, "product_name": product_name,
            "product_sku": product_sku, "usage_metric": usage_metric,
            "usage_quantity": usage_quantity, "discount_type": discount_type,
            "discount_value": discount_value, "tax_rate": tax_rate,
            "notes": notes, "sort_order": sort_order, "agent_id": agent_id,
            "item_type": item_type, "metadata": metadata,
        }.items():
            if val is not None:
                payload[key] = val

        _log.debug("Adding line item to order: %s", order_id)
        resp = self._http.post(f"{self._resource_path}?action=line-items", json=payload)
        return resp.data

    def remove_line_item(self, line_item_id: str) -> None:
        """Remove a line item from an order."""
        self._http.request(
            "DELETE",
            f"{self._resource_path}?action=line-items",
            json={"id": line_item_id},
        )
