from __future__ import annotations

from datetime import date, datetime

from sqlalchemy import Boolean, Date, DateTime, Float, ForeignKey, Index, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.db.session import Base


class ThroughputProduct(Base):
    __tablename__ = "throughput_products"
    __table_args__ = (
        Index("ix_throughput_products_tenant_item", "tenant_id", "item_id", unique=True),
        Index("ix_throughput_products_tenant_name", "tenant_id", "name"),
    )

    id: Mapped[int] = mapped_column(primary_key=True)
    tenant_id: Mapped[str] = mapped_column(String(64), default="default", index=True)
    item_id: Mapped[str | None] = mapped_column(String(64), nullable=True)
    name: Mapped[str] = mapped_column(String(255))
    client_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
    default_bag_size: Mapped[float | None] = mapped_column(Float, nullable=True)
    is_bulka_default: Mapped[bool] = mapped_column(Boolean, default=False)
    active: Mapped[bool] = mapped_column(Boolean, default=True)
    is_stock_item: Mapped[bool] = mapped_column(Boolean, default=True)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    entries: Mapped[list["ProductionThroughput"]] = relationship(back_populates="product")


class ProductionThroughput(Base):
    __tablename__ = "production_throughput_entries"
    __table_args__ = (
        Index("ix_throughput_entries_tenant_date", "tenant_id", "production_date"),
    )

    id: Mapped[int] = mapped_column(primary_key=True)
    tenant_id: Mapped[str] = mapped_column(String(64), default="default", index=True)
    production_date: Mapped[date] = mapped_column(Date)
    product_id: Mapped[int | None] = mapped_column(ForeignKey("throughput_products.id"), nullable=True, index=True)
    product_name_snapshot: Mapped[str] = mapped_column(String(255))
    bag_size: Mapped[float | None] = mapped_column(Float, nullable=True)

    scales_checked: Mapped[bool] = mapped_column(Boolean, default=True)
    label_correct: Mapped[bool] = mapped_column(Boolean, default=True)
    bag_sealed: Mapped[bool] = mapped_column(Boolean, default=True)
    pallet_good_condition: Mapped[bool] = mapped_column(Boolean, default=True)

    # Where the run is destined. A run can be for a client order, for stock, or
    # split across both. job_number records the Order Circle job for the order
    # portion; stock_quantity records how much of a split goes into stock (in the
    # same unit as `quantity`).
    for_order: Mapped[bool] = mapped_column(Boolean, default=False)
    for_stock: Mapped[bool] = mapped_column(Boolean, default=False)
    job_number: Mapped[str | None] = mapped_column(String(64), nullable=True)
    stock_quantity: Mapped[float | None] = mapped_column(Float, nullable=True)

    sample_box_no: Mapped[str | None] = mapped_column(String(64), nullable=True)

    test_weight_1: Mapped[float | None] = mapped_column(Float, nullable=True)
    test_weight_2: Mapped[float | None] = mapped_column(Float, nullable=True)
    test_weight_3: Mapped[float | None] = mapped_column(Float, nullable=True)
    test_weight_4: Mapped[float | None] = mapped_column(Float, nullable=True)
    test_weight_5: Mapped[float | None] = mapped_column(Float, nullable=True)

    quantity: Mapped[float] = mapped_column(Float, default=0.0)
    quantity_type: Mapped[str] = mapped_column(String(8), default="bags")
    calculated_kg: Mapped[float] = mapped_column(Float, default=0.0)

    staff_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)

    created_by: Mapped[str | None] = mapped_column(String(255), nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    product: Mapped[ThroughputProduct | None] = relationship(back_populates="entries")
