"""V1 core interceptor logic — sign, validate, encode for x402 V1 protocol."""

from __future__ import annotations

import base64
import json
from typing import Any, Optional

from ..types import (
    NetworkType,
    StacksAccount,
    X402PaymentRequired,
    PaymentResponse,
    TokenType,
)
from ..stacks_tx.keys import private_key_to_address
from ..stacks_tx.transaction import build_stx_transfer, build_contract_call
from ..stacks_tx.clarity import (
    serialize_uint,
    serialize_standard_principal,
    serialize_optional_none,
    serialize_optional_some,
    serialize_buffer_from_string,
)
from ..utils import asset_from_v2, network_from_caip2


def private_key_to_account_v1(
    private_key: str, network: NetworkType = "testnet"
) -> StacksAccount:
    """Create a Stacks account from a private key (V1)."""
    address = private_key_to_address(private_key, network)
    return StacksAccount(address=address, private_key=private_key, network=network)


def decode_x_payment_response(header: Optional[str]) -> Optional[PaymentResponse]:
    """Decode the X-PAYMENT-RESPONSE header from base64 JSON."""
    if not header:
        return None
    try:
        decoded = base64.b64decode(header).decode("utf-8")
        data = json.loads(decoded)
        return PaymentResponse.model_validate(data)
    except Exception:
        return None


def encode_x_payment_response(response: PaymentResponse) -> str:
    """Encode a payment response to base64 JSON."""
    return base64.b64encode(
        json.dumps(response.model_dump(by_alias=True)).encode()
    ).decode()


def sign_payment_for_request(
    payment_request: X402PaymentRequired,
    account: StacksAccount,
) -> str:
    """Sign a payment transaction based on x402 V1 payment request.

    Returns the signed transaction hex.
    """
    amount = int(payment_request.max_amount_required)
    token_type: TokenType = payment_request.token_type or "STX"
    memo = payment_request.nonce[:34]

    if token_type in ("sBTC", "USDCx"):
        if not payment_request.token_contract:
            raise ValueError(f"Token contract required for {token_type} payments")

        fn_args = [
            serialize_uint(amount),
            serialize_standard_principal(account.address),
            serialize_standard_principal(payment_request.pay_to),
            (
                serialize_optional_some(serialize_buffer_from_string(memo))
                if memo
                else serialize_optional_none()
            ),
        ]
        return build_contract_call(
            account.private_key,
            payment_request.token_contract.address,
            payment_request.token_contract.name,
            "transfer",
            fn_args,
            network=payment_request.network,
        )
    else:
        return build_stx_transfer(
            account.private_key,
            payment_request.pay_to,
            amount,
            memo=memo,
            network=payment_request.network,
        )


def is_valid_payment_request(data: Any) -> bool:
    """Validate that data is a valid x402 V1 payment request."""
    if not isinstance(data, dict):
        return False
    return (
        isinstance(data.get("maxAmountRequired"), str)
        and isinstance(data.get("resource"), str)
        and isinstance(data.get("payTo"), str)
        and isinstance(data.get("network"), str)
        and isinstance(data.get("nonce"), str)
        and isinstance(data.get("expiresAt"), str)
        and data.get("network") in ("mainnet", "testnet")
    )
