"""Subscribers API endpoint mixin."""

import logging
from typing import TYPE_CHECKING, Any, Literal

from pydantic import ValidationError as PydanticValidationError

from growflow_billing.exceptions import ConflictError, GrowFlowBillingError
from growflow_billing.models.subscriber import BillingAddress, Subscriber

if TYPE_CHECKING:
    from growflow_billing.client import GrowFlowBillingClient

logger = logging.getLogger(__name__)


class SubscribersMixin:
    """Mixin for subscriber-related API calls."""

    async def create_subscriber(
        self: "GrowFlowBillingClient",
        external_id: str,
        email: str,
        name: str | None = None,
        customer_type: Literal["individual", "business"] | None = None,
        first_name: str | None = None,
        last_name: str | None = None,
        fiscal_code: str | None = None,
        company_name: str | None = None,
        vat_number: str | None = None,
        pec_email: str | None = None,
        sdi_code: str | None = None,
        phone: str | None = None,
        billing_address: BillingAddress | dict[str, Any] | None = None,
        custom_data: dict[str, Any] | None = None,
    ) -> Subscriber:
        """Create a new subscriber.

        If subscriber already exists (409 Conflict), returns existing subscriber.

        Args:
            external_id: Your internal customer ID
            email: Subscriber email
            name: Subscriber name
            customer_type: "individual" or "business"
            first_name: First name (individual)
            last_name: Last name (individual)
            fiscal_code: Italian tax ID / Codice Fiscale (individual)
            company_name: Company name (business)
            vat_number: VAT/Tax ID / Partita IVA (business)
            pec_email: PEC email for electronic invoicing (business)
            sdi_code: SDI code / Sistema di Interscambio (business)
            phone: Contact phone number
            billing_address: Billing address
            custom_data: Custom metadata

        Returns:
            Subscriber object

        Example:
            subscriber = await client.create_subscriber(
                external_id="store_123",
                email="owner@store.com",
                name="My Store",
                customer_type="business",
                company_name="My Store SRL",
                vat_number="IT12345678901",
                pec_email="mystore@pec.it",
                sdi_code="ABCDEFG",
            )
        """
        payload: dict[str, Any] = {
            "external_id": external_id,
            "email": email,
        }
        if name:
            payload["name"] = name
        if customer_type:
            payload["customer_type"] = customer_type
        if first_name:
            payload["first_name"] = first_name
        if last_name:
            payload["last_name"] = last_name
        if fiscal_code:
            payload["fiscal_code"] = fiscal_code
        if company_name:
            payload["company_name"] = company_name
        if vat_number:
            payload["vat_number"] = vat_number
        if pec_email:
            payload["pec_email"] = pec_email
        if sdi_code:
            payload["sdi_code"] = sdi_code
        if phone:
            payload["phone"] = phone
        if billing_address:
            if isinstance(billing_address, BillingAddress):
                payload["billing_address"] = billing_address.model_dump(exclude_none=True)
            else:
                payload["billing_address"] = billing_address
        if custom_data:
            payload["custom_data"] = custom_data

        try:
            response = await self._request("POST", "/subscribers", json=payload)
            try:
                return Subscriber(**response)
            except PydanticValidationError as e:
                logger.error(f"Failed to parse subscriber response: {e}")
                raise GrowFlowBillingError(
                    f"Invalid subscriber data from API: {e}",
                ) from e
        except ConflictError:
            # Subscriber already exists, fetch and return
            return await self.get_subscriber(external_id)

    async def get_subscriber(self: "GrowFlowBillingClient", external_id: str) -> Subscriber:
        """Get subscriber by external ID.

        Args:
            external_id: Your internal customer ID

        Returns:
            Subscriber object

        Raises:
            NotFoundError: If subscriber not found
            GrowFlowBillingError: If response cannot be parsed
        """
        response = await self._request("GET", f"/subscribers/{external_id}")
        try:
            return Subscriber(**response)
        except PydanticValidationError as e:
            logger.error(f"Failed to parse subscriber response: {e}")
            raise GrowFlowBillingError(
                f"Invalid subscriber data from API: {e}",
            ) from e

    async def update_subscriber(
        self: "GrowFlowBillingClient",
        external_id: str,
        *,
        email: str | None = None,
        name: str | None = None,
        customer_type: Literal["individual", "business"] | None = None,
        first_name: str | None = None,
        last_name: str | None = None,
        fiscal_code: str | None = None,
        company_name: str | None = None,
        vat_number: str | None = None,
        pec_email: str | None = None,
        sdi_code: str | None = None,
        phone: str | None = None,
        billing_address: BillingAddress | dict[str, Any] | None = None,
        custom_data: dict[str, Any] | None = None,
        **extra_fields: Any,
    ) -> Subscriber:
        """Update subscriber information.

        Args:
            external_id: Your internal customer ID
            email: New email
            name: New name
            customer_type: "individual" or "business"
            first_name: First name (individual)
            last_name: Last name (individual)
            fiscal_code: Italian tax ID / Codice Fiscale
            company_name: Company name (business)
            vat_number: VAT/Tax ID / Partita IVA
            pec_email: PEC email for electronic invoicing
            sdi_code: SDI code / Sistema di Interscambio
            phone: Contact phone number
            billing_address: New billing address
            custom_data: New custom metadata
            **extra_fields: Additional fields to pass through to the API

        Returns:
            Updated Subscriber object
        """
        payload: dict[str, Any] = {}
        # Build payload from explicit parameters
        for field_name, value in [
            ("email", email),
            ("name", name),
            ("customer_type", customer_type),
            ("first_name", first_name),
            ("last_name", last_name),
            ("fiscal_code", fiscal_code),
            ("company_name", company_name),
            ("vat_number", vat_number),
            ("pec_email", pec_email),
            ("sdi_code", sdi_code),
            ("phone", phone),
        ]:
            if value is not None:
                payload[field_name] = value

        if billing_address:
            if isinstance(billing_address, BillingAddress):
                payload["billing_address"] = billing_address.model_dump(exclude_none=True)
            else:
                payload["billing_address"] = billing_address
        if custom_data:
            payload["custom_data"] = custom_data

        # Pass through any extra fields
        payload.update(extra_fields)

        response = await self._request("PATCH", f"/subscribers/{external_id}", json=payload)
        try:
            return Subscriber(**response)
        except PydanticValidationError as e:
            logger.error(f"Failed to parse subscriber response: {e}")
            raise GrowFlowBillingError(
                f"Invalid subscriber data from API: {e}",
            ) from e
