# /opt/docker/dev/service_finder/backend/app/models/marketplace/payment.py
"""
Payment Intent modell a Stripe integrációhoz és belső fizetésekhez.
Kettős Lakat (Double Lock) biztonságot valósít meg.
"""

import enum
import uuid
from datetime import datetime
from typing import Any, Optional
from sqlalchemy import String, DateTime, JSON, ForeignKey, Numeric, Boolean, Integer, text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.dialects.postgresql import UUID as PG_UUID, ENUM as PG_ENUM
from sqlalchemy.sql import func

from app.database import Base
from app.models.system.audit import WalletType


class PaymentIntentStatus(str, enum.Enum):
    """PaymentIntent státuszok."""
    PENDING = "PENDING"          # Létrehozva, vár Stripe fizetésre
    PROCESSING = "PROCESSING"    # Fizetés folyamatban (belső ajándékozás)
    COMPLETED = "COMPLETED"      # Sikeresen teljesítve
    FAILED = "FAILED"            # Sikertelen (pl. Stripe hiba)
    CANCELLED = "CANCELLED"      # Felhasználó által törölve
    EXPIRED = "EXPIRED"          # Lejárt (pl. Stripe session timeout)


class PaymentIntent(Base):
    """
    Fizetési szándék (Prior Intent) a Kettős Lakat biztonsághoz.
    
    Minden külső (Stripe) vagy belső fizetés előtt létre kell hozni egy PENDING
    státuszú PaymentIntent-et. A Stripe metadata tartalmazza az intent_token-t,
    így a webhook validáció során vissza lehet keresni.
    
    Fontos mezők:
    - net_amount: A kedvezményezett által kapott összeg (pénztárcába kerül)
    - handling_fee: Kényelmi díj (rendszer bevétele)
    - gross_amount: net_amount + handling_fee (Stripe-nak küldött összeg)
    """
    __tablename__ = "payment_intents"
    __table_args__ = {"schema": "finance"}
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    
    # Egyedi token a Stripe metadata számára
    intent_token: Mapped[uuid.UUID] = mapped_column(
        PG_UUID(as_uuid=True), default=uuid.uuid4, unique=True, nullable=False, index=True
    )
    
    # Fizető felhasználó
    payer_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id"), nullable=False)
    payer: Mapped["User"] = relationship("User", foreign_keys=[payer_id], back_populates="payment_intents_as_payer")
    
    # Kedvezményezett felhasználó (opcionális, ha None, akkor a rendszernek fizet)
    beneficiary_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
    beneficiary: Mapped[Optional["User"]] = relationship("User", foreign_keys=[beneficiary_id], back_populates="payment_intents_as_beneficiary")
    
    # Cél pénztárca típusa
    target_wallet_type: Mapped[WalletType] = mapped_column(
        PG_ENUM(WalletType, name="wallet_type", schema="finance"),
        nullable=False
    )
    
    # Összeg mezők (javított a kényelmi díj kezelésére)
    net_amount: Mapped[float] = mapped_column(Numeric(18, 4), nullable=False, comment="Kedvezményezett által kapott összeg")
    handling_fee: Mapped[float] = mapped_column(Numeric(18, 4), default=0.0, comment="Kényelmi díj")
    gross_amount: Mapped[float] = mapped_column(Numeric(18, 4), nullable=False, comment="Fizetendő összeg (net + fee)")
    
    currency: Mapped[str] = mapped_column(String(10), default="EUR", nullable=False)
    
    # Státusz
    status: Mapped[PaymentIntentStatus] = mapped_column(
        PG_ENUM(PaymentIntentStatus, name="payment_intent_status", schema="finance"),
        default=PaymentIntentStatus.PENDING,
        nullable=False,
        index=True
    )
    
    # Stripe információk (külső fizetés esetén)
    stripe_session_id: Mapped[Optional[str]] = mapped_column(String(255), unique=True, index=True)
    stripe_payment_intent_id: Mapped[Optional[str]] = mapped_column(String(255), index=True)
    stripe_customer_id: Mapped[Optional[str]] = mapped_column(String(255))
    
    # Metaadatok (metadata foglalt név SQLAlchemy-ban, ezért meta_data)
    meta_data: Mapped[Any] = mapped_column(JSON, server_default=text("'{}'::jsonb"), name="metadata")
    
    # Időbélyegek
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
    completed_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), comment="Stripe session lejárati ideje")
    
    # Tranzakció kapcsolat
    transaction_id: Mapped[Optional[uuid.UUID]] = mapped_column(PG_UUID(as_uuid=True), comment="Kapcsolódó FinancialLedger transaction_id")
    
    # Soft delete
    is_deleted: Mapped[bool] = mapped_column(Boolean, default=False)
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    
    def __repr__(self) -> str:
        return f"<PaymentIntent {self.id}: {self.status} {self.gross_amount}{self.currency}>"
    
    def mark_completed(self, transaction_id: Optional[uuid.UUID] = None) -> None:
        """PaymentIntent befejezése sikeres fizetés után."""
        self.status = PaymentIntentStatus.COMPLETED
        self.completed_at = datetime.utcnow()
        if transaction_id:
            self.transaction_id = transaction_id
    
    def mark_failed(self, reason: Optional[str] = None) -> None:
        """PaymentIntent sikertelen státuszba helyezése."""
        self.status = PaymentIntentStatus.FAILED
        if reason and self.meta_data:
            self.meta_data = {**self.meta_data, "failure_reason": reason}
    
    def is_valid_for_webhook(self) -> bool:
        """Ellenőrzi, hogy a PaymentIntent érvényes-e webhook feldolgozásra."""
        return (
            self.status == PaymentIntentStatus.PENDING
            and not self.is_deleted
            and (self.expires_at is None or self.expires_at > datetime.utcnow())
        )


# Import User modell a relationship-ekhez (circular import elkerülésére)
from app.models.identity import User


class WithdrawalPayoutMethod(str, enum.Enum):
    """Kifizetési módok."""
    FIAT_BANK = "FIAT_BANK"      # Banki átutalás (SEPA)
    CRYPTO_USDT = "CRYPTO_USDT"  # USDT (ERC20/TRC20)


class WithdrawalRequestStatus(str, enum.Enum):
    """Kifizetési kérelem státuszai."""
    PENDING = "PENDING"          # Beküldve, admin ellenőrzésre vár
    APPROVED = "APPROVED"        # Jóváhagyva, kifizetés folyamatban
    REJECTED = "REJECTED"        # Elutasítva (pl. hiányzó bizonylat)
    COMPLETED = "COMPLETED"      # Kifizetés teljesítve
    CANCELLED = "CANCELLED"      # Felhasználó által visszavonva


class WithdrawalRequest(Base):
    """
    Kifizetési kérelem (Withdrawal Request) a felhasználók Earned zsebéből való pénzkivételhez.
    
    A felhasználó beküld egy kérést, amely admin jóváhagyást igényel.
    Ha 14 napon belül nem kerül jóváhagyásra, automatikusan REJECTED lesz és a pénz visszakerül a Earned zsebbe.
    """
    __tablename__ = "withdrawal_requests"
    __table_args__ = {"schema": "finance"}
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    
    # Felhasználó aki a kérést benyújtotta
    user_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id"), nullable=False)
    user: Mapped["User"] = relationship("User", back_populates="withdrawal_requests", foreign_keys=[user_id])
    
    # Összeg és pénznem
    amount: Mapped[float] = mapped_column(Numeric(18, 4), nullable=False)
    currency: Mapped[str] = mapped_column(String(10), default="EUR", nullable=False)
    
    # Kifizetési mód
    payout_method: Mapped[WithdrawalPayoutMethod] = mapped_column(
        PG_ENUM(WithdrawalPayoutMethod, name="withdrawal_payout_method", schema="finance"),
        nullable=False
    )
    
    # Státusz
    status: Mapped[WithdrawalRequestStatus] = mapped_column(
        PG_ENUM(WithdrawalRequestStatus, name="withdrawal_request_status", schema="finance"),
        default=WithdrawalRequestStatus.PENDING,
        nullable=False,
        index=True
    )
    
    # Okozata (pl. admin megjegyzés vagy automatikus elutasítás oka)
    reason: Mapped[Optional[str]] = mapped_column(String(500))
    
    # Admin információk
    approved_by_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
    approved_by: Mapped[Optional["User"]] = relationship("User", foreign_keys=[approved_by_id])
    approved_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    
    # Tranzakció kapcsolat (ha a pénz visszakerül a zsebbe)
    refund_transaction_id: Mapped[Optional[uuid.UUID]] = mapped_column(PG_UUID(as_uuid=True))
    
    # Időbélyegek
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
    
    # Soft delete
    is_deleted: Mapped[bool] = mapped_column(Boolean, default=False)
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
    
    def __repr__(self) -> str:
        return f"<WithdrawalRequest {self.id}: {self.status} {self.amount}{self.currency}>"
    
    def approve(self, admin_user_id: int) -> None:
        """Admin jóváhagyás."""
        self.status = WithdrawalRequestStatus.APPROVED
        self.approved_by_id = admin_user_id
        self.approved_at = datetime.utcnow()
        self.reason = None
    
    def reject(self, reason: str) -> None:
        """Admin elutasítás."""
        self.status = WithdrawalRequestStatus.REJECTED
        self.reason = reason
    
    def cancel(self) -> None:
        """Felhasználó visszavonja a kérést."""
        self.status = WithdrawalRequestStatus.CANCELLED
        self.reason = "User cancelled"
    
    def is_expired(self, days: int = 14) -> bool:
        """Ellenőrzi, hogy a kérelem lejárt-e (14 nap)."""
        from datetime import timedelta
        expiry_date = self.created_at + timedelta(days=days)
        return datetime.utcnow() > expiry_date