from typing import List, Optional, TYPE_CHECKING
from sqlalchemy import (
    Boolean,
    Integer,
    DateTime,
    ForeignKey,
    String,
    Text,
    case,
    Float,
)
from sqlalchemy.orm import relationship, Session, Mapped, mapped_column
from datetime import datetime
from src.apps.base.models.base import Base
from src.core.utils.enums import PaymentMethodScopes, PaymentMethodTypes
from sqlalchemy.sql import func
from sqlalchemy.ext.hybrid import hybrid_property
from src.apps.payment_methods.models.payment_method_ach_details import PaymentMethodAchDetails
from src.apps.payment_methods.models.payment_method_card_details import PaymentMethodCardDetails


class MerchantPaymentMethod(Base):
    """
    MerchantPaymentMethod Model: ORM class for MerchantPaymentMethod Entity
    """

    __tablename__ = "merchant_payment_methods"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True, autoincrement=True)
    method: Mapped[str] = mapped_column(String(50), default=PaymentMethodTypes.CARD)    
    is_connected: Mapped[bool] = mapped_column(Boolean, default=False)
    in_use: Mapped[bool] = mapped_column(Boolean, default=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True, onupdate=func.now())
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)       

    merchant_id: Mapped[int] = mapped_column(Integer, ForeignKey("merchants.id"))
    
    # TODO: Uncomment when PaymentMethodCardDetails model is created
    card_details_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("payment_methods_card_details.id"), nullable=True
    )
    card_details: Mapped[Optional["PaymentMethodCardDetails"]] = relationship("PaymentMethodCardDetails")

    # TODO: Uncomment when PaymentMethodAchDetails model is created
    ach_details_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("payment_methods_ach_details.id"), nullable=True
    )
    ach_details: Mapped[Optional["PaymentMethodAchDetails"]] = relationship("PaymentMethodAchDetails")
    
    billing_address_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("address.id"), nullable=True)

    # TODO: Uncomment when PaymentMethodCardDetails and PaymentMethodAchDetails models are created
    @hybrid_property
    def reference_id(self) -> str:
        if self.method == PaymentMethodTypes.CARD:
            return self.card_details.reference_id
        elif self.method == PaymentMethodTypes.ACH:
            return self.ach_details.reference_id
        return ""

    @reference_id.expression
    def reference_id(cls):
        return case(
            (
                cls.method == PaymentMethodTypes.ACH,
                PaymentMethodAchDetails.reference_id,
            ),
            (
                cls.method == PaymentMethodTypes.CARD,
                PaymentMethodCardDetails.reference_id,
            ),
            else_="N.A",
        )

