"""End-to-End Reconciliation model — actual losses per tank over a complete drain-refill cycle."""

from __future__ import annotations

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

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

from app.models.base import Base, TimestampMixin

if TYPE_CHECKING:
    from app.models.spbu import Tangki
    from app.models.user import User


class StatusEndToEnd(str, enum.Enum):
    OPEN = "open"
    CLOSED = "closed"


class EndToEndCycle(Base, TimestampMixin):
    """One end-to-end reconciliation cycle per tank.

    Tracks actual losses from tank-empty to tank-empty, bypassing
    sounding margin of error.
    """

    __tablename__ = "end_to_end_cycle"

    __table_args__ = (
        # Max 1 open cycle per tank — enforced at DB level
        Index(
            "ix_e2e_tangki_open",
            "tangki_id",
            unique=True,
            postgresql_where="status = 'open'",
        ),
        Index("ix_e2e_spbu_id", "spbu_id"),
    )

    id: Mapped[int] = mapped_column(primary_key=True)
    spbu_id: Mapped[int] = mapped_column(
        ForeignKey("master_spbu.id", ondelete="CASCADE"), nullable=False
    )
    tangki_id: Mapped[int] = mapped_column(
        ForeignKey("master_spbu_tangki.id", ondelete="RESTRICT"), nullable=False
    )
    status: Mapped[str] = mapped_column(
        String(10), nullable=False, default=StatusEndToEnd.OPEN
    )

    tanggal_mulai: Mapped[date] = mapped_column(Date, nullable=False)
    tanggal_selesai: Mapped[date | None] = mapped_column(Date, nullable=True)

    # Dead stock = volume remaining when tank "can't sell anymore"
    dead_stock_awal: Mapped[Decimal] = mapped_column(
        Numeric(15, 3), nullable=False, default=Decimal("0")
    )
    dead_stock_akhir: Mapped[Decimal | None] = mapped_column(
        Numeric(15, 3), nullable=True
    )

    # Frozen totals — filled when cycle is closed
    total_penerimaan: Mapped[Decimal] = mapped_column(
        Numeric(15, 3), nullable=False, default=Decimal("0")
    )
    total_penjualan: Mapped[Decimal] = mapped_column(
        Numeric(15, 3), nullable=False, default=Decimal("0")
    )
    total_pemindahan_in: Mapped[Decimal] = mapped_column(
        Numeric(15, 3), nullable=False, default=Decimal("0")
    )
    total_pemindahan_out: Mapped[Decimal] = mapped_column(
        Numeric(15, 3), nullable=False, default=Decimal("0")
    )

    # Calculated on close
    losses_aktual: Mapped[Decimal | None] = mapped_column(
        Numeric(15, 3), nullable=True
    )
    losses_pct: Mapped[Decimal | None] = mapped_column(
        Numeric(8, 4), nullable=True
    )

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

    # Relationships
    tangki: Mapped["Tangki"] = relationship(foreign_keys=[tangki_id])
    started_by: Mapped["User | None"] = relationship(foreign_keys=[started_by_id])
    closed_by: Mapped["User | None"] = relationship(foreign_keys=[closed_by_id])
