from sqlalchemy import Integer, ForeignKey, String, Text, Float, DateTime, Table, Column
from sqlalchemy.orm import relationship, Mapped, mapped_column
from sqlalchemy.sql import func
from src.apps.base.models.base import Base
from sqlalchemy.ext.hybrid import hybrid_property
from src.core.config import settings
from typing import Optional, List
from datetime import datetime


receipt_attachments_map = Table(
    "receipts_files",
    Base.metadata,
    Column("receipt_id", Integer, ForeignKey("receipts.id")),
    Column("file_id", Integer, ForeignKey("files.id")),
)


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

    __tablename__ = "receipts"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True, autoincrement=True)
    receipt_id: Mapped[str] = mapped_column(String(255), unique=True, index=True)
    receipt_literal: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    amount: Mapped[float] = mapped_column(Float, default=0.0)
    paid_date: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    billing_date: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    tax_fee: Mapped[float] = mapped_column(Float, default=0.0)
    shipping_fee: Mapped[float] = mapped_column(Float, default=0.0)
    tip: Mapped[float] = mapped_column(Float, default=0.0)
    charge: Mapped[float] = mapped_column(Float, default=0.0)
    additional_fee: Mapped[float] = mapped_column(Float, default=0.0)
    comments: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    description: Mapped[Optional[str]] = mapped_column(Text, nullable=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)

    payment_request_id: Mapped[int] = mapped_column(Integer, ForeignKey("payment_requests.id"))
    payment_request: Mapped["PaymentRequest"] = relationship("PaymentRequest")

    merchant_id: Mapped[int] = mapped_column(Integer, ForeignKey("merchants.id"))
    merchant: Mapped["Merchant"] = relationship("Merchant")

    customer_id: Mapped[int] = mapped_column(Integer, ForeignKey("customers.id"))
    customer: Mapped["Customer"] = relationship("Customer")

    # TODO: Uncomment when Transactions model is created
    transaction_id: Mapped[int] = mapped_column(Integer, ForeignKey("transactions.id"))
    transaction: Mapped["Transactions"] = relationship("Transactions")

    attachments: Mapped[List["File"]] = relationship("File", secondary=receipt_attachments_map)

    @hybrid_property
    def download_url(self) -> str:
        url = f"{settings.SERVER_HOST}{settings.API_ROUTE_PREFIX}/receipts/{self.receipt_id}/download"
        return url
