"""
ProviderTransaction model — stores the raw payment-provider response
for each transaction so it can be audited and displayed in the UI.

One row is created per charge attempt. For TSYS this captures the full
SaleResponse (or AchResponse) alongside the key fields extracted from it.
"""
from datetime import datetime, timezone

from sqlalchemy import DateTime, Float, ForeignKey, Integer, JSON, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func

from src.apps.base.models.base import Base


class ProviderTransaction(Base):
    __tablename__ = "provider_transactions"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)

    # FK to the HubWallet transaction record this response belongs to
    transaction_id: Mapped[int] = mapped_column(
        ForeignKey("transactions.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )

    # Which payment provider produced this response
    provider_slug: Mapped[str] = mapped_column(String(50), nullable=False)

    # ── Key fields extracted from the provider response ───────────────────
    provider_txn_id: Mapped[str | None] = mapped_column(
        String(255), nullable=True,
        comment="TSYS transactionID — use for refunds/voids",
    )
    host_reference_number: Mapped[str | None] = mapped_column(
        String(255), nullable=True,
        comment="TSYS hostReferenceNumber (bank ref, not usable for refunds)",
    )
    response_code: Mapped[str | None] = mapped_column(
        String(50), nullable=True,
        comment="approvalCode / responseCode from provider",
    )
    authorization_code: Mapped[str | None] = mapped_column(
        String(100), nullable=True,
    )
    card_type: Mapped[str | None] = mapped_column(
        String(50), nullable=True,
        comment="e.g. VISA, MC, AMEX",
    )
    masked_card_number: Mapped[str | None] = mapped_column(
        String(50), nullable=True,
        comment="Masked/last-4 card number from provider response",
    )
    avs_response_code: Mapped[str | None] = mapped_column(String(10), nullable=True)
    cvv_response_code: Mapped[str | None] = mapped_column(String(10), nullable=True)

    amount: Mapped[float | None] = mapped_column(Float, nullable=True)
    currency: Mapped[str | None] = mapped_column(String(10), nullable=True)

    # "succeeded" | "failed" | "refunded"
    status: Mapped[str | None] = mapped_column(String(50), nullable=True)

    # Full raw response from the provider (entire SaleResponse / AchResponse dict)
    raw_response: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        nullable=False,
    )

    # Relationship back to the parent transaction (lazy — not eagerly loaded)
    transaction: Mapped["Transactions"] = relationship(  # type: ignore[name-defined]
        "Transactions",
        back_populates="provider_transactions",
    )
