from __future__ import annotations

from datetime import datetime
from typing import Optional, List

from sqlalchemy import Integer, String, DateTime, ForeignKey, Numeric, func, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from shared.db.base import Base


class Order(Base):
    __tablename__ = "orders"

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

    user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id"), nullable=True)
    session_id: Mapped[Optional[str]] = mapped_column(String(64), index=True, nullable=True)

    page_config_id: Mapped[Optional[int]] = mapped_column(
        ForeignKey("page_configs.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )

    status: Mapped[str] = mapped_column(
        String(32),
        nullable=False,
        default="pending",
        server_default="pending",
    )
    currency: Mapped[str] = mapped_column(String(16), nullable=False, default="GBP")
    total_amount: Mapped[float] = mapped_column(Numeric(12, 2), nullable=False)

    # free-form description for the order
    description: Mapped[Optional[str]] = mapped_column(Text, nullable=True, index=True)

    # SumUp reference string (what we send as checkout_reference)
    sumup_reference: Mapped[Optional[str]] = mapped_column(
        String(255),
        nullable=True,
        index=True,
    )

    # SumUp integration fields
    sumup_checkout_id: Mapped[Optional[str]] = mapped_column(
        String(128),
        nullable=True,
        index=True,
    )
    sumup_status: Mapped[Optional[str]] = mapped_column(String(32), nullable=True)
    sumup_hosted_url: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

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

    items: Mapped[List["OrderItem"]] = relationship(
        "OrderItem",
        back_populates="order",
        cascade="all, delete-orphan",
        lazy="selectin",
    )
    page_config: Mapped[Optional["PageConfig"]] = relationship(
        "PageConfig",
        foreign_keys=[page_config_id],
        lazy="selectin",
    )


class OrderItem(Base):
    __tablename__ = "order_items"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    order_id: Mapped[int] = mapped_column(
        ForeignKey("orders.id", ondelete="CASCADE"),
        nullable=False,
    )

    product_id: Mapped[int] = mapped_column(
        ForeignKey("products.id"),
        nullable=False,
    )
    product_title: Mapped[Optional[str]] = mapped_column(String(512), nullable=True)

    quantity: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
    unit_price: Mapped[float] = mapped_column(Numeric(12, 2), nullable=False)
    currency: Mapped[str] = mapped_column(String(16), nullable=False, default="GBP")

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

    order: Mapped["Order"] = relationship(
        "Order",
        back_populates="items",
    )

    # NEW: link each order item to its product
    product: Mapped["Product"] = relationship(
        "Product",
        back_populates="order_items",
        lazy="selectin",
    )
