"""Checkout ORM model."""
from datetime import datetime
from typing import Optional, List, TYPE_CHECKING

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

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

if TYPE_CHECKING:
    from src.apps.checkouts.models.checkout_link import CheckoutLink
    from src.apps.checkouts.models.checkout_line_item import CheckoutLineItem
    from src.apps.checkouts.models.checkout_activity import CheckoutActivity
    from src.apps.payment_requests.models.payment_request import PaymentRequest
    from src.apps.merchants.models.merchant import Merchant


class Checkout(Base):
    __tablename__ = "checkouts"

    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)
    checkout_literal: Mapped[Optional[str]] = mapped_column(String(20), unique=True, nullable=True, index=True)

    # Display
    title: Mapped[str] = mapped_column(String(255), nullable=False)
    description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

    # Type & Status
    checkout_type: Mapped[str] = mapped_column(String(30), nullable=False, default="MERCHANT_DEFINED")
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="DRAFT")

    # Amount config (MERCHANT_DEFINED)
    amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True, default=0.0)
    currency: Mapped[str] = mapped_column(String(3), nullable=False, default="USD")

    # Amount config (PAYER_DEFINED)
    min_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
    max_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
    suggested_amounts: Mapped[Optional[list]] = mapped_column(JSON, nullable=True)
    default_amount: Mapped[Optional[float]] = mapped_column(Float, nullable=True)

    # Tax config
    tax_percent: Mapped[Optional[float]] = mapped_column(Float, default=0.0, nullable=True)
    tax_type: Mapped[Optional[str]] = mapped_column(String(30), default="notax", nullable=True)

    # Tip config
    tip_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    tip_type: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
    tip_percentages: Mapped[Optional[list]] = mapped_column(JSON, nullable=True)
    tip_allow_custom: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)

    # Payment config
    payment_frequency: Mapped[str] = mapped_column(String(50), nullable=False, default="SINGLE")
    authorization_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    authorization_method: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
    require_billing_address: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    require_cvv: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    split_config: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
    recurring_config: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)

    # Payer verification
    require_payer_verification: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    payer_verification_type: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)

    # Link lifecycle
    expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    allow_link_regeneration: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)

    # Post-payment
    redirect_url: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    thank_you_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

    # Additional settings (cost adjustment, discount, late fee, attachment)
    adjustment_config: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)

    # Timestamps + soft delete
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True, onupdate=func.now())
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)

    # Relationships
    merchant: Mapped[Optional["Merchant"]] = relationship("Merchant", foreign_keys=[merchant_id])
    links: Mapped[List["CheckoutLink"]] = relationship(
        "CheckoutLink", back_populates="checkout", cascade="all, delete-orphan"
    )
    line_items: Mapped[List["CheckoutLineItem"]] = relationship(
        "CheckoutLineItem", back_populates="checkout", cascade="all, delete-orphan"
    )
    activities: Mapped[List["CheckoutActivity"]] = relationship(
        "CheckoutActivity", back_populates="checkout", cascade="all, delete-orphan"
    )
    payment_requests: Mapped[List["PaymentRequest"]] = relationship(
        "PaymentRequest", back_populates="checkout"
    )
