"""Penyetoran models — per-shift cash deposit + batch submission."""

from __future__ import annotations

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

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

from app.models.base import Base, TimestampMixin

if TYPE_CHECKING:
    from app.models.spbu import Spbu
    from app.models.user import User
    from app.models.operational import LaporanShift


class StatusPenyetoran(str, enum.Enum):
    DRAFT = "draft"
    SUBMITTED = "submitted"
    APPROVED = "approved"


class StatusPenyetoranBatch(str, enum.Enum):
    DRAFT = "draft"
    SUBMITTED = "submitted"
    APPROVED = "approved"


class Penyetoran(Base, TimestampMixin):
    """One cash deposit record per laporan_shift (auto-created when sales is saved)."""

    __tablename__ = "penyetoran"

    __table_args__ = (
        UniqueConstraint("laporan_shift_id", name="uq_penyetoran_laporan_shift"),
        Index("ix_penyetoran_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
    )
    laporan_shift_id: Mapped[int] = mapped_column(
        ForeignKey("laporan_shift.id", ondelete="CASCADE"), nullable=False
    )
    tanggal: Mapped[date] = mapped_column(Date, nullable=False)
    shift_id: Mapped[int] = mapped_column(
        ForeignKey("master_spbu_shift.id", ondelete="RESTRICT"), nullable=False
    )

    # Total kas (sum of all denomination amounts from laporan_shift)
    jumlah_kas: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    # Total non-cash (kartu + qr + instansi from laporan_shift)
    jumlah_non_kas: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    # Total penjualan (from laporan_shift, for verification)
    total_penjualan: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))

    catatan: Mapped[str | None] = mapped_column(Text, nullable=True)
    bukti_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default=StatusPenyetoran.DRAFT)

    # Batch reference (set when SPBU Admin includes this in a submission batch)
    batch_id: Mapped[int | None] = mapped_column(
        ForeignKey("penyetoran_batch.id", ondelete="SET NULL"), nullable=True, index=True
    )

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

    # Relationships
    spbu: Mapped["Spbu"] = relationship(foreign_keys=[spbu_id])
    laporan_shift: Mapped["LaporanShift"] = relationship(foreign_keys=[laporan_shift_id])
    created_by: Mapped["User | None"] = relationship(foreign_keys=[created_by_id])
    batch: Mapped["PenyetoranBatch | None"] = relationship(foreign_keys=[batch_id], back_populates="items")


class PenyetoranBatch(Base, TimestampMixin):
    """Grouped batch of penyetoran records submitted by SPBU Admin to Manager for approval."""

    __tablename__ = "penyetoran_batch"

    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_from: Mapped[date] = mapped_column(Date, nullable=False)
    tanggal_to: Mapped[date] = mapped_column(Date, nullable=False)
    total_amount: Mapped[Decimal] = mapped_column(Numeric(15, 3), nullable=False, default=Decimal("0"))
    catatan: Mapped[str | None] = mapped_column(Text, nullable=True)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default=StatusPenyetoranBatch.SUBMITTED)

    # Audit trail
    submitted_by_id: Mapped[int | None] = mapped_column(
        ForeignKey("master_user.id", ondelete="SET NULL"), nullable=True
    )
    submitted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    reviewed_by_id: Mapped[int | None] = mapped_column(
        ForeignKey("master_user.id", ondelete="SET NULL"), nullable=True
    )
    reviewed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    catatan_review: Mapped[str | None] = mapped_column(Text, nullable=True)
    unlock_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    unlocked_by_id: Mapped[int | None] = mapped_column(
        ForeignKey("master_user.id", ondelete="SET NULL"), nullable=True
    )
    unlocked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    # Relationships
    spbu: Mapped["Spbu"] = relationship(foreign_keys=[spbu_id])
    submitted_by: Mapped["User | None"] = relationship(foreign_keys=[submitted_by_id])
    reviewed_by: Mapped["User | None"] = relationship(foreign_keys=[reviewed_by_id])
    unlocked_by: Mapped["User | None"] = relationship(foreign_keys=[unlocked_by_id])
    items: Mapped[list["Penyetoran"]] = relationship(back_populates="batch")
