"""Pemindahan produk repository — DB queries for product transfers."""

from datetime import date

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from app.models.pemindahan import PemindahanProduk


def _eager_options():
    return [
        selectinload(PemindahanProduk.tangki_sumber),
        selectinload(PemindahanProduk.tangki_tujuan),
        selectinload(PemindahanProduk.produk_lama),
        selectinload(PemindahanProduk.user),
    ]


async def get_all(
    db: AsyncSession,
    spbu_id: int,
    tanggal_mulai: date | None = None,
    tanggal_akhir: date | None = None,
    skip: int = 0,
    limit: int = 50,
) -> list[PemindahanProduk]:
    stmt = (
        select(PemindahanProduk)
        .options(*_eager_options())
        .where(PemindahanProduk.spbu_id == spbu_id)
        .order_by(PemindahanProduk.tanggal.desc(), PemindahanProduk.id.desc())
        .offset(skip)
        .limit(limit)
    )
    if tanggal_mulai:
        stmt = stmt.where(PemindahanProduk.tanggal >= tanggal_mulai)
    if tanggal_akhir:
        stmt = stmt.where(PemindahanProduk.tanggal <= tanggal_akhir)
    result = await db.execute(stmt)
    return list(result.scalars().all())


async def get_by_id(db: AsyncSession, spbu_id: int, pemindahan_id: int) -> PemindahanProduk | None:
    stmt = (
        select(PemindahanProduk)
        .options(*_eager_options())
        .where(PemindahanProduk.spbu_id == spbu_id, PemindahanProduk.id == pemindahan_id)
    )
    result = await db.execute(stmt)
    return result.scalar_one_or_none()


async def get_by_tangki_date_range(
    db: AsyncSession,
    tangki_id: int,
    tanggal_mulai: date,
    tanggal_akhir: date,
) -> list[PemindahanProduk]:
    """Get transfers involving a tank as source or destination within date range."""
    stmt = (
        select(PemindahanProduk)
        .where(
            PemindahanProduk.tanggal >= tanggal_mulai,
            PemindahanProduk.tanggal <= tanggal_akhir,
            (PemindahanProduk.tangki_sumber_id == tangki_id)
            | (PemindahanProduk.tangki_tujuan_id == tangki_id),
        )
        .order_by(PemindahanProduk.tanggal)
    )
    result = await db.execute(stmt)
    return list(result.scalars().all())


async def create(db: AsyncSession, pemindahan: PemindahanProduk) -> PemindahanProduk:
    db.add(pemindahan)
    await db.flush()
    await db.refresh(pemindahan, attribute_names=["tangki_sumber", "tangki_tujuan", "produk_lama", "user"])
    return pemindahan
