"""Mint core — signing, persistence, idempotency, revoke."""

from __future__ import annotations

from decimal import Decimal

import pytest

from app.adapters.base import SaleEvent
from app.mint import mint_from_sale, revoke_license
from app.models import License
from datatools_license.crypto import decode_blob, verify


def _sale(**overrides) -> SaleEvent:
    base = dict(
        source="manual",
        source_order_id=None,
        buyer_name="Jane Doe",
        buyer_email="jane@example.com",
        tier="core",
        years=1,
        promotion=None,
        amount_paid=None,
        currency="USD",
        notes=None,
    )
    base.update(overrides)
    return SaleEvent(**base)


def test_mint_persists_and_signs_verifiably(db_session):
    row = mint_from_sale(db_session, _sale())
    db_session.commit()

    assert row.license_key.startswith("DT1-CORE-")
    assert row.tier == "core"
    assert row.source == "manual"
    assert row.blob.startswith("DTLIC2:")
    assert row.revoked_at is None

    payload = decode_blob(row.blob)
    sig = payload.pop("signature")
    assert verify(payload, sig), "minted blob must verify against the dev pubkey"
    assert payload["name"] == "Jane Doe"
    assert payload["email"] == "jane@example.com"
    assert payload["tier"] == "core"


def test_mint_idempotent_on_source_order_id(db_session):
    """A second mint with the same (source, source_order_id) returns
    the existing row — webhook retries cannot double-mint."""
    first = mint_from_sale(
        db_session,
        _sale(source="gumroad", source_order_id="GUM-1001"),
    )
    db_session.commit()

    second = mint_from_sale(
        db_session,
        _sale(source="gumroad", source_order_id="GUM-1001", buyer_name="Different Name"),
    )
    db_session.commit()

    assert first.license_key == second.license_key
    assert second.name == "Jane Doe", "existing row is returned unchanged"


def test_manual_mints_never_dedup(db_session):
    """source_order_id=None means each manual mint creates a new row."""
    a = mint_from_sale(db_session, _sale())
    db_session.commit()
    b = mint_from_sale(db_session, _sale())
    db_session.commit()
    assert a.license_key != b.license_key


def test_mint_records_commercial_metadata(db_session):
    row = mint_from_sale(
        db_session,
        _sale(promotion="LAUNCH50", amount_paid=Decimal("79.00"), currency="USD"),
    )
    db_session.commit()
    assert row.promotion == "LAUNCH50"
    assert Decimal(str(row.amount_paid)) == Decimal("79.00")
    assert row.currency == "USD"


def test_revoke_marks_row(db_session):
    row = mint_from_sale(db_session, _sale())
    db_session.commit()

    revoked = revoke_license(db_session, license_key=row.license_key, reason="refund")
    db_session.commit()

    assert revoked is not None
    assert revoked.revoked_at is not None
    assert "refund" in (revoked.notes or "")


def test_revoke_unknown_returns_none(db_session):
    assert revoke_license(db_session, license_key="DT1-CORE-no-such-key") is None
