from typing import Optional, TYPE_CHECKING
from sqlalchemy import String, Boolean, Integer, DateTime, JSON, ForeignKey, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func
from src.apps.base.models.base import Base
from datetime import datetime

if TYPE_CHECKING:
    from src.apps.payment_providers.models.payment_provider import PaymentProvider
    from src.apps.merchants.models.merchant import Merchant

ONBOARDING_STATUS_VALUES = ("not_started", "in_progress", "pending_review", "active", "suspended", "rejected")


class MerchantProviderConfig(Base):
    __tablename__ = "merchant_provider_configs"
    __table_args__ = (
        UniqueConstraint("merchant_id", "provider_id", name="uq_merchant_provider_configs_merchant_provider"),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True, autoincrement=True)
    merchant_id: Mapped[int] = mapped_column(Integer, ForeignKey("merchants.id"), nullable=False, index=True)
    provider_id: Mapped[int] = mapped_column(Integer, ForeignKey("payment_providers.id"), nullable=False, index=True)
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
    onboarding_status: Mapped[str] = mapped_column(String(30), default="not_started", nullable=False)
    config_data: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True, onupdate=func.now())
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)

    merchant: Mapped["Merchant"] = relationship("Merchant", back_populates="provider_configs")
    provider: Mapped["PaymentProvider"] = relationship("PaymentProvider", back_populates="merchant_provider_configs")
    credentials: Mapped[list["MerchantProviderCredential"]] = relationship(
        "MerchantProviderCredential", back_populates="config", cascade="all, delete-orphan"
    )
