"""V2 type definitions for x402 payment protocol (Coinbase compatible)."""

from __future__ import annotations

from typing import Any, Literal, Optional

from pydantic import BaseModel, ConfigDict, Field


# CAIP-2 Network identifiers for Stacks
STACKS_NETWORKS = {
    "MAINNET": "stacks:1",
    "TESTNET": "stacks:2147483648",
}

# x402 HTTP header names (V2 protocol)
X402_HEADERS = {
    "PAYMENT_REQUIRED": "payment-required",
    "PAYMENT_SIGNATURE": "payment-signature",
    "PAYMENT_RESPONSE": "payment-response",
}

# Standard x402 error codes
X402_ERROR_CODES = {
    "INSUFFICIENT_FUNDS": "insufficient_funds",
    "INVALID_NETWORK": "invalid_network",
    "INVALID_PAYLOAD": "invalid_payload",
    "INVALID_PAYMENT_REQUIREMENTS": "invalid_payment_requirements",
    "INVALID_SCHEME": "invalid_scheme",
    "UNSUPPORTED_SCHEME": "unsupported_scheme",
    "INVALID_X402_VERSION": "invalid_x402_version",
    "INVALID_TRANSACTION_STATE": "invalid_transaction_state",
    "UNEXPECTED_VERIFY_ERROR": "unexpected_verify_error",
    "UNEXPECTED_SETTLE_ERROR": "unexpected_settle_error",
    "RECIPIENT_MISMATCH": "recipient_mismatch",
    "AMOUNT_INSUFFICIENT": "amount_insufficient",
    "SENDER_MISMATCH": "sender_mismatch",
    "TRANSACTION_NOT_FOUND": "transaction_not_found",
    "TRANSACTION_PENDING": "transaction_pending",
    "TRANSACTION_FAILED": "transaction_failed",
    "BROADCAST_FAILED": "broadcast_failed",
}


class ResourceInfo(BaseModel):
    """Information about the protected resource."""

    model_config = ConfigDict(populate_by_name=True)

    url: str
    description: Optional[str] = None
    mime_type: Optional[str] = Field(default=None, alias="mimeType")


class PaymentRequirementsV2(BaseModel):
    """Payment requirements for x402 v2 protocol."""

    model_config = ConfigDict(populate_by_name=True)

    scheme: str
    network: str  # CAIP-2 format, e.g. "stacks:1"
    amount: str
    asset: str
    pay_to: str = Field(alias="payTo")
    max_timeout_seconds: int = Field(alias="maxTimeoutSeconds")
    extra: Optional[dict[str, Any]] = None


class PaymentRequiredV2(BaseModel):
    """Payment required response for x402 v2 protocol."""

    model_config = ConfigDict(populate_by_name=True)

    x402_version: Literal[2] = Field(alias="x402Version")
    error: Optional[str] = None
    resource: ResourceInfo
    accepts: list[PaymentRequirementsV2]
    extensions: Optional[dict[str, Any]] = None


class StacksPayloadV2(BaseModel):
    """Stacks-specific payment payload (transaction data)."""

    transaction: str


class PaymentPayloadV2(BaseModel):
    """Payment payload for x402 v2 protocol."""

    model_config = ConfigDict(populate_by_name=True)

    x402_version: Literal[2] = Field(alias="x402Version")
    resource: Optional[ResourceInfo] = None
    accepted: PaymentRequirementsV2
    payload: StacksPayloadV2
    extensions: Optional[dict[str, Any]] = None


class VerifyResponseV2(BaseModel):
    """Verification response for x402 v2 protocol."""

    model_config = ConfigDict(populate_by_name=True)

    is_valid: bool = Field(alias="isValid")
    invalid_reason: Optional[str] = Field(default=None, alias="invalidReason")
    payer: Optional[str] = None


class SettlementResponseV2(BaseModel):
    """Settlement response for x402 v2 protocol."""

    model_config = ConfigDict(populate_by_name=True)

    success: bool
    error_reason: Optional[str] = Field(default=None, alias="errorReason")
    payer: Optional[str] = None
    transaction: str
    network: str  # CAIP-2 format


class FacilitatorVerifyRequestV2(BaseModel):
    """Request body for POST /verify endpoint."""

    model_config = ConfigDict(populate_by_name=True)

    x402_version: Literal[2] = Field(alias="x402Version")
    payment_payload: PaymentPayloadV2 = Field(alias="paymentPayload")
    payment_requirements: PaymentRequirementsV2 = Field(alias="paymentRequirements")


class FacilitatorSettleRequestV2(BaseModel):
    """Request body for POST /settle endpoint."""

    model_config = ConfigDict(populate_by_name=True)

    x402_version: Literal[2] = Field(alias="x402Version")
    payment_payload: PaymentPayloadV2 = Field(alias="paymentPayload")
    payment_requirements: PaymentRequirementsV2 = Field(alias="paymentRequirements")


class SupportedKind(BaseModel):
    """A supported payment kind."""

    model_config = ConfigDict(populate_by_name=True)

    x402_version: int = Field(alias="x402Version")
    scheme: str
    network: str
    extra: Optional[dict[str, Any]] = None


class SupportedResponse(BaseModel):
    """Response from GET /supported endpoint."""

    kinds: list[SupportedKind]
    extensions: list[str]
    signers: dict[str, list[str]]
