"""Penebusan models — BBM procurement from Pertamina."""

import enum
from datetime import date, datetime
from decimal import Decimal

from sqlalchemy import (
    Boolean,
    Date,
    DateTime,
    ForeignKey,
    Index,
    Numeric,
    String,
    UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.models.base import Base, TimestampMixin


class StatusPenebusan(str, enum.Enum):
    DRAFT = "draft"
    WAITING_SO = "waiting_so"
    SUBMITTED = "submitted"
    PARTIALLY_RECEIVED = "partially_received"
    FULLY_RECEIVED = "fully_received"


class Penebusan(Base, TimestampMixin):
    """One BBM procurement booking from Pertamina."""

    __tablename__ = "penebusan"

    __table_args__ = (
        UniqueConstraint("spbu_id", "booking_code", name="uq_penebusan_spbu_booking"),
        Index("ix_penebusan_spbu_tanggal", "spbu_id", "tanggal"),
    )

    id: Mapped[int] = mapped_column(primary_key=True)
    spbu_id: Mapped[int] = mapped_column(
        ForeignKey("master_spbu.id", ondelete="CASCADE"), nullable=False, index=True
    )
    tanggal: Mapped[date] = mapped_column(Date, nullable=False)
    booking_code: Mapped[str] = mapped_column(String(50), nullable=False)
    no_so: Mapped[str | None] = mapped_column(String(50), nullable=True)
    status: Mapped[StatusPenebusan] = mapped_column(
        String(30), nullable=False, default=StatusPenebusan.DRAFT
    )

    # Cost breakdown (Indonesian names as requested)
    subtotal: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    discount: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    ppn: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    pph22: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    pbbkb: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    rounding: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    debit_credit: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    total: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))

    # Manual / paksa bongkar flag (dummy DO created by system)
    is_manual: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)

    # File uploads
    pdf_do_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
    pdf_bukti_bayar_url: Mapped[str | None] = mapped_column(String(500), nullable=True)

    # Audit
    created_by_id: Mapped[int | None] = mapped_column(
        ForeignKey("master_user.id", ondelete="SET NULL"), nullable=True
    )

    # Relationships
    items: Mapped[list["PenebusanItem"]] = relationship(
        back_populates="penebusan", cascade="all, delete-orphan"
    )
    spbu: Mapped["Spbu"] = relationship(foreign_keys=[spbu_id])
    created_by: Mapped["User | None"] = relationship(foreign_keys=[created_by_id])


class PenebusanItem(Base):
    """One line item (product) inside a Penebusan booking."""

    __tablename__ = "penebusan_item"

    __table_args__ = (
        Index("ix_penebusan_item_penebusan_id", "penebusan_id"),
    )

    id: Mapped[int] = mapped_column(primary_key=True)
    penebusan_id: Mapped[int] = mapped_column(
        ForeignKey("penebusan.id", ondelete="CASCADE"), nullable=False
    )
    produk_id: Mapped[int] = mapped_column(
        ForeignKey("master_produk.id", ondelete="RESTRICT"), nullable=False
    )
    kode_item_pertamina: Mapped[str | None] = mapped_column(String(50), nullable=True)
    volume_pesan: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False)
    volume_diterima: Mapped[Decimal] = mapped_column(
        Numeric(15, 3), nullable=False, default=Decimal("0")
    )
    tanggal_kirim: Mapped[date | None] = mapped_column(Date, nullable=True)
    sent_to_text: Mapped[str | None] = mapped_column(String(200), nullable=True)

    # Relationships
    penebusan: Mapped["Penebusan"] = relationship(back_populates="items")
    produk: Mapped["Produk"] = relationship(foreign_keys=[produk_id])


# Avoid circular imports
from app.models.product import Produk  # noqa: E402, F401
from app.models.spbu import Spbu  # noqa: E402, F401
from app.models.user import User  # noqa: E402, F401
