from __future__ import annotations

import httpx

from .models import (
    CampaignCreateRequest,
    CampaignDetail,
    CampaignSendResponse,
    EmailLog,
    NewsletterCreateRequest,
    NewsletterDetail,
    PaginatedCampaignListList,
    PaginatedEmailLogList,
    PaginatedNewsletterListList,
    PaginatedSubscriptionListList,
    PatchedNewsletterUpdateRequest,
    SubscribeRequest,
    SubscribeResponse,
    SubscriptionList,
    UnsubscribeRequest,
)


class SyncNewsletterNewsletterAPI:
    """Synchronous API endpoints for Newsletter."""

    def __init__(self, client: httpx.Client):
        """Initialize sync sub-client with shared httpx client."""
        self._client = client

    def campaigns_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedCampaignListList]:
        """
        List campaigns

        ViewSet for newsletter campaign management.
        """
        url = "/api/newsletter/campaigns/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedCampaignListList.model_validate(response.json())


    def campaigns_create(self, data: CampaignCreateRequest) -> CampaignDetail:
        """
        Create campaign (draft)

        ViewSet for newsletter campaign management.
        """
        url = "/api/newsletter/campaigns/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return CampaignDetail.model_validate(response.json())


    def campaigns_retrieve(self, id: str) -> CampaignDetail:
        """
        Campaign detail

        ViewSet for newsletter campaign management.
        """
        url = f"/api/newsletter/campaigns/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return CampaignDetail.model_validate(response.json())


    def campaigns_send_create(self, id: str) -> CampaignSendResponse:
        """
        Send a draft campaign to all active subscribers

        Send a campaign. Must be in draft status.
        """
        url = f"/api/newsletter/campaigns/{id}/send/"
        response = self._client.post(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return CampaignSendResponse.model_validate(response.json())


    def logs_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedEmailLogList]:
        """
        List email logs

        Read-only ViewSet for email logs.
        """
        url = "/api/newsletter/logs/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedEmailLogList.model_validate(response.json())


    def logs_retrieve(self, id: str) -> EmailLog:
        """
        Email log detail

        Read-only ViewSet for email logs.
        """
        url = f"/api/newsletter/logs/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return EmailLog.model_validate(response.json())


    def newsletters_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedNewsletterListList]:
        """
        List newsletters

        ViewSet for newsletter management.
        """
        url = "/api/newsletter/newsletters/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedNewsletterListList.model_validate(response.json())


    def newsletters_create(self, data: NewsletterCreateRequest) -> NewsletterDetail:
        """
        Create newsletter

        Override to return NewsletterDetailSerializer in the response.
        """
        url = "/api/newsletter/newsletters/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return NewsletterDetail.model_validate(response.json())


    def newsletters_retrieve(self, id: str) -> NewsletterDetail:
        """
        Newsletter detail

        ViewSet for newsletter management.
        """
        url = f"/api/newsletter/newsletters/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return NewsletterDetail.model_validate(response.json())


    def newsletters_partial_update(
        self,
        id: str,
        data: PatchedNewsletterUpdateRequest | None = None,
    ) -> NewsletterDetail:
        """
        Update newsletter

        ViewSet for newsletter management.
        """
        url = f"/api/newsletter/newsletters/{id}/"
        _json = data.model_dump(mode="json", exclude_unset=True, exclude_none=True) if data else None
        response = self._client.patch(url, json=_json)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return NewsletterDetail.model_validate(response.json())


    def newsletters_destroy(self, id: str) -> None:
        """
        ViewSet for newsletter management.
        """
        url = f"/api/newsletter/newsletters/{id}/"
        response = self._client.delete(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return None


    def subscriptions_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedSubscriptionListList]:
        """
        List subscriptions

        ViewSet for newsletter subscription management.
        """
        url = "/api/newsletter/subscriptions/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedSubscriptionListList.model_validate(response.json())


    def subscriptions_retrieve(self, id: str) -> SubscriptionList:
        """
        Subscription detail

        ViewSet for newsletter subscription management.
        """
        url = f"/api/newsletter/subscriptions/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return SubscriptionList.model_validate(response.json())


    def subscriptions_subscribe_create(self, data: SubscribeRequest) -> SubscribeResponse:
        """
        Subscribe to a newsletter (public)

        Subscribe an email to a newsletter. Public endpoint.
        """
        url = "/api/newsletter/subscriptions/subscribe/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return SubscribeResponse.model_validate(response.json())


    def subscriptions_unsubscribe_create(
        self,
        data: UnsubscribeRequest,
    ) -> SubscribeResponse:
        """
        Unsubscribe from a newsletter (public)

        Unsubscribe from a newsletter. Public endpoint.
        """
        url = "/api/newsletter/subscriptions/unsubscribe/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return SubscribeResponse.model_validate(response.json())


