"""Webhooks handling for the Meemo Python client.

This module provides the Webhooks class for managing webhook registrations
and viewing delivery logs for the Meemo External API.

Authors:
    GDP Labs

References:
    https://gdplabs.gitbook.io/meemo/resources/external-api-documentation
"""

import logging

from meemo._base import _ERR_EXPECTED_DICT, _ERR_EXPECTED_LIST, _BaseService, _BaseWebhooksMixin
from meemo.models import (
    AvailableOrganization,
    Webhook,
    WebhookEvent,
    WebhookEventListResponse,
    WebhookListResponse,
)

logger = logging.getLogger(__name__)


class Webhooks(_BaseService, _BaseWebhooksMixin):
    """Handles Webhooks API operations for the Meemo External API."""

    def list_available_organizations(
        self,
        extra_headers: dict[str, str] | None = None,
    ) -> list[AvailableOrganization]:
        """List organizations accessible to your external application.

        Use these IDs when creating webhooks.

        Args:
            extra_headers: Additional headers.

        Returns:
            List of available organizations.

        Raises:
            httpx.HTTPStatusError: If the API request fails.
        """
        logger.debug("Listing available organizations for webhooks")
        url = self._webhooks_url("available-organizations/")
        headers = self._prepare_headers(extra_headers)
        data = self._make_request("GET", url, headers)
        if not isinstance(data, list):
            raise TypeError(_ERR_EXPECTED_LIST)
        return [AvailableOrganization(**item) for item in data]

    def create_webhook(
        self,
        target_url: str,
        events: list[str],
        organization_ids: list[int],
        description: str | None = None,
        extra_headers: dict[str, str] | None = None,
    ) -> list[Webhook]:
        """Register a new webhook for one or more organizations.

        The API returns one webhook object per organization.

        Args:
            target_url: HTTPS URL where events will be sent.
            events: List of event types (e.g. meeting.created, meeting.transcription_completed).
            organization_ids: List of organization IDs to monitor.
            description: Optional description of the webhook.
            extra_headers: Additional headers.

        Returns:
            List of created webhook objects (one per organization).

        Raises:
            httpx.HTTPStatusError: If the API request fails.
        """
        logger.debug("Creating webhook for organizations: %s", organization_ids)
        url = self._webhooks_url()
        headers = self._prepare_headers(extra_headers)
        headers["Content-Type"] = "application/json"
        json_data = self._build_create_webhook_body(
            target_url=target_url,
            events=events,
            organization_ids=organization_ids,
            description=description,
        )
        data = self._make_request("POST", url, headers, json_data=json_data)
        if not isinstance(data, list):
            raise TypeError(_ERR_EXPECTED_LIST)
        return [Webhook(**item) for item in data]

    def list_webhooks(
        self,
        extra_headers: dict[str, str] | None = None,
    ) -> WebhookListResponse:
        """List all webhooks registered for your accessible organizations.

        Args:
            extra_headers: Additional headers.

        Returns:
            Paginated list of webhooks.

        Raises:
            httpx.HTTPStatusError: If the API request fails.
        """
        logger.debug("Listing webhooks")
        url = self._webhooks_url()
        headers = self._prepare_headers(extra_headers)
        data = self._make_request("GET", url, headers)
        if not isinstance(data, dict):
            raise TypeError(_ERR_EXPECTED_DICT)
        return WebhookListResponse(**data)

    def get_webhook(
        self,
        webhook_id: int,
        extra_headers: dict[str, str] | None = None,
    ) -> Webhook:
        """Get details of a specific webhook.

        Args:
            webhook_id: Webhook ID.
            extra_headers: Additional headers.

        Returns:
            Webhook details including failure_count and last_failure_reason.

        Raises:
            ValueError: If webhook_id is not a positive integer.
            httpx.HTTPStatusError: If the API request fails.
        """
        self._validate_webhook_id(webhook_id)
        logger.debug("Retrieving webhook: %d", webhook_id)
        url = self._webhooks_url(f"{webhook_id}/")
        headers = self._prepare_headers(extra_headers)
        data = self._make_request("GET", url, headers)
        if not isinstance(data, dict):
            raise TypeError(_ERR_EXPECTED_DICT)
        return Webhook(**data)

    def delete_webhook(
        self,
        webhook_id: int,
        extra_headers: dict[str, str] | None = None,
    ) -> None:
        """Delete a webhook.

        Args:
            webhook_id: Webhook ID.
            extra_headers: Additional headers.

        Raises:
            ValueError: If webhook_id is not a positive integer.
            httpx.HTTPStatusError: If the API request fails.
        """
        self._validate_webhook_id(webhook_id)
        logger.debug("Deleting webhook: %d", webhook_id)
        url = self._webhooks_url(f"{webhook_id}/")
        headers = self._prepare_headers(extra_headers)
        self._make_request("DELETE", url, headers)

    def list_webhook_events(
        self,
        webhook_id: int | None = None,
        extra_headers: dict[str, str] | None = None,
    ) -> WebhookEventListResponse:
        """List webhook delivery logs.

        Args:
            webhook_id: Optional. Filter by specific webhook ID.
            extra_headers: Additional headers.

        Returns:
            Paginated list of webhook event logs.

        Raises:
            httpx.HTTPStatusError: If the API request fails.
        """
        logger.debug("Listing webhook events (webhook_id=%s)", webhook_id)
        url = self._webhook_events_url()
        headers = self._prepare_headers(extra_headers)
        params = {"webhook_id": webhook_id} if webhook_id is not None else None
        data = self._make_request("GET", url, headers, params=params)
        if not isinstance(data, dict):
            raise TypeError(_ERR_EXPECTED_DICT)
        return WebhookEventListResponse(**data)

    def get_webhook_event(
        self,
        event_id: int,
        extra_headers: dict[str, str] | None = None,
    ) -> WebhookEvent:
        """Get details of a specific webhook event log.

        Args:
            event_id: Webhook event log ID.
            extra_headers: Additional headers.

        Returns:
            Webhook event log details.

        Raises:
            ValueError: If event_id is not a positive integer.
            httpx.HTTPStatusError: If the API request fails.
        """
        self._validate_event_id(event_id)
        logger.debug("Retrieving webhook event: %d", event_id)
        url = self._webhook_events_url(f"{event_id}/")
        headers = self._prepare_headers(extra_headers)
        data = self._make_request("GET", url, headers)
        if not isinstance(data, dict):
            raise TypeError(_ERR_EXPECTED_DICT)
        return WebhookEvent(**data)
