"""Tests for Pydantic type models."""

import json
from x402_stacks.types import (
    X402PaymentRequired,
    PaymentDetails,
    StacksAccount,
    PaymentResponse,
    VerifiedPayment,
)
from x402_stacks.types_v2 import (
    PaymentRequiredV2,
    PaymentRequirementsV2,
    PaymentPayloadV2,
    SettlementResponseV2,
    StacksPayloadV2,
    ResourceInfo,
    STACKS_NETWORKS,
    X402_HEADERS,
    X402_ERROR_CODES,
)


class TestV1Types:
    def test_payment_required_camel_case(self):
        data = {
            "maxAmountRequired": "1000000",
            "resource": "/api/data",
            "payTo": "ST123",
            "network": "testnet",
            "nonce": "abc123",
            "expiresAt": "2025-01-01T00:00:00Z",
        }
        req = X402PaymentRequired.model_validate(data)
        assert req.max_amount_required == "1000000"
        assert req.pay_to == "ST123"

        # Serialize back to camelCase
        dumped = req.model_dump(by_alias=True)
        assert dumped["maxAmountRequired"] == "1000000"
        assert dumped["payTo"] == "ST123"

    def test_payment_required_json_roundtrip(self):
        data = {
            "maxAmountRequired": "500000",
            "resource": "/test",
            "payTo": "ST456",
            "network": "mainnet",
            "nonce": "xyz",
            "expiresAt": "2025-06-01T00:00:00Z",
            "tokenType": "sBTC",
        }
        req = X402PaymentRequired.model_validate(data)
        json_str = req.model_dump_json(by_alias=True)
        parsed = json.loads(json_str)
        req2 = X402PaymentRequired.model_validate(parsed)
        assert req2.max_amount_required == req.max_amount_required
        assert req2.token_type == "sBTC"

    def test_stacks_account(self):
        acct = StacksAccount.model_validate({
            "address": "ST123",
            "privateKey": "deadbeef",
            "network": "testnet",
        })
        assert acct.private_key == "deadbeef"

    def test_verified_payment(self):
        vp = VerifiedPayment.model_validate({
            "txId": "abc",
            "status": "success",
            "sender": "ST1",
            "recipient": "ST2",
            "amount": 1000000,
            "isValid": True,
        })
        assert vp.is_valid is True
        assert vp.tx_id == "abc"


class TestV2Types:
    def test_payment_required_v2(self):
        data = {
            "x402Version": 2,
            "resource": {"url": "http://example.com/api"},
            "accepts": [{
                "scheme": "exact",
                "network": "stacks:1",
                "amount": "1000000",
                "asset": "STX",
                "payTo": "SP123",
                "maxTimeoutSeconds": 300,
            }],
        }
        req = PaymentRequiredV2.model_validate(data)
        assert req.x402_version == 2
        assert len(req.accepts) == 1
        assert req.accepts[0].pay_to == "SP123"

    def test_settlement_response_v2(self):
        data = {
            "success": True,
            "transaction": "0xdeadbeef",
            "network": "stacks:1",
            "payer": "SP123",
        }
        resp = SettlementResponseV2.model_validate(data)
        assert resp.success is True
        assert resp.payer == "SP123"

    def test_constants(self):
        assert STACKS_NETWORKS["MAINNET"] == "stacks:1"
        assert STACKS_NETWORKS["TESTNET"] == "stacks:2147483648"
        assert X402_HEADERS["PAYMENT_SIGNATURE"] == "payment-signature"
        assert "INSUFFICIENT_FUNDS" in X402_ERROR_CODES

    def test_payment_payload_v2(self):
        payload = PaymentPayloadV2(
            x402_version=2,
            accepted=PaymentRequirementsV2(
                scheme="exact",
                network="stacks:1",
                amount="1000",
                asset="STX",
                pay_to="SP123",
                max_timeout_seconds=300,
            ),
            payload=StacksPayloadV2(transaction="deadbeef"),
        )
        dumped = payload.model_dump(by_alias=True)
        assert dumped["x402Version"] == 2
        assert dumped["payload"]["transaction"] == "deadbeef"
