"""Request models for HAX SDK."""

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any

from pydantic import BaseModel, ConfigDict, Field

from hax.models.delivery import DeliveryResult


class RequestStatus(str, Enum):
    """Status of a HAX request."""

    PENDING = "pending"
    OPENED = "opened"
    COMPLETED = "completed"
    EXPIRED = "expired"
    CANCELLED = "cancelled"


class RequestSummary(BaseModel):
    """Minimal request info returned from list endpoint."""

    model_config = ConfigDict(populate_by_name=True)

    id: str
    type: str
    status: RequestStatus
    created_at: datetime = Field(alias="createdAt")


class CreatedRequest(BaseModel):
    """Response from creating a request."""

    model_config = ConfigDict(populate_by_name=True)

    id: str
    url: str
    type: str
    title: str | None = None
    description: str | None = None
    payload: dict[str, Any]
    metadata: dict[str, Any] | None = None
    webhook_url: str | None = Field(default=None, alias="webhookUrl")
    status: RequestStatus
    created_at: datetime = Field(alias="createdAt")
    expires_at: datetime | None = Field(default=None, alias="expiresAt")
    user_id: str | None = Field(default=None, alias="userId")
    delivery: DeliveryResult | None = None

    @property
    def is_pending(self) -> bool:
        """Check if the request is pending."""
        return self.status == RequestStatus.PENDING

    @property
    def is_opened(self) -> bool:
        """Check if the request has been opened."""
        return self.status == RequestStatus.OPENED

    @property
    def is_completed(self) -> bool:
        """Check if the request is completed."""
        return self.status == RequestStatus.COMPLETED

    @property
    def is_expired(self) -> bool:
        """Check if the request is expired."""
        return self.status == RequestStatus.EXPIRED

    @property
    def is_cancelled(self) -> bool:
        """Check if the request is cancelled."""
        return self.status == RequestStatus.CANCELLED


class Request(BaseModel):
    """Full request model with all fields."""

    model_config = ConfigDict(populate_by_name=True)

    id: str
    project_id: str = Field(alias="projectId")
    type: str
    title: str | None = None
    description: str | None = None
    payload: dict[str, Any]
    metadata: dict[str, Any] | None = None
    status: RequestStatus
    expires_at: datetime | None = Field(default=None, alias="expiresAt")
    response: dict[str, Any] | None = None
    responded_by: str | None = Field(default=None, alias="respondedBy")
    responded_at: datetime | None = Field(default=None, alias="respondedAt")
    webhook_url: str | None = Field(default=None, alias="webhookUrl")
    opened_at: datetime | None = Field(default=None, alias="openedAt")
    user_id: str | None = Field(default=None, alias="userId")
    created_at: datetime = Field(alias="createdAt")
    updated_at: datetime = Field(alias="updatedAt")

    # Base URL is set by the client after parsing
    _base_url: str = ""

    def set_base_url(self, base_url: str) -> None:
        """Set the base URL for generating request URLs."""
        self._base_url = base_url.rstrip("/").replace("/api/v1", "")

    @property
    def url(self) -> str:
        """Get the URL for a human to respond to this request.

        Points to the Response Hub at /hub/r/[requestId].
        """
        if self._base_url:
            return f"{self._base_url}/hub/r/{self.id}"
        return f"/hub/r/{self.id}"

    @property
    def is_pending(self) -> bool:
        """Check if the request is pending."""
        return self.status == RequestStatus.PENDING

    @property
    def is_opened(self) -> bool:
        """Check if the request has been opened."""
        return self.status == RequestStatus.OPENED

    @property
    def is_completed(self) -> bool:
        """Check if the request is completed."""
        return self.status == RequestStatus.COMPLETED

    @property
    def is_expired(self) -> bool:
        """Check if the request is expired."""
        return self.status == RequestStatus.EXPIRED

    @property
    def is_cancelled(self) -> bool:
        """Check if the request is cancelled."""
        return self.status == RequestStatus.CANCELLED

    @property
    def verifiable_credential(self) -> dict[str, Any] | None:
        """Get the verifiable credential from the response if present."""
        if self.response and "vc" in self.response:
            return self.response["vc"]  # type: ignore[no-any-return]
        return None
