"""Pemindahan produk service — business logic for product transfers."""

from datetime import date
from decimal import Decimal

from sqlalchemy.exc import IntegrityError, SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.pemindahan import PemindahanProduk
from app.repositories import pemindahan_repository
from app.schemas.pemindahan import PemindahanCreate, PemindahanResponse


def _to_response(row: PemindahanProduk) -> PemindahanResponse:
    return PemindahanResponse(
        id=row.id,
        spbu_id=row.spbu_id,
        tanggal=row.tanggal,
        jam=row.jam,
        tangki_sumber_id=row.tangki_sumber_id,
        tangki_sumber_nama=row.tangki_sumber.nama if row.tangki_sumber else None,
        produk_lama_id=row.produk_lama_id,
        produk_lama_nama=row.produk_lama.nama if row.produk_lama else None,
        tangki_tujuan_id=row.tangki_tujuan_id,
        tangki_tujuan_nama=row.tangki_tujuan.nama if row.tangki_tujuan else None,
        volume_sumber_sebelum=row.volume_sumber_sebelum,
        volume_tujuan_sebelum=row.volume_tujuan_sebelum,
        volume_tujuan_sesudah=row.volume_tujuan_sesudah,
        volume_masuk=row.volume_masuk,
        losses_transfer=row.losses_transfer,
        catatan=row.catatan,
        dilakukan_oleh=row.dilakukan_oleh,
        dilakukan_oleh_nama=row.user.name if row.user else None,
        created_at=row.created_at,
        updated_at=row.updated_at,
    )


async def list_pemindahan(
    db: AsyncSession,
    spbu_id: int,
    tanggal_mulai: date | None = None,
    tanggal_akhir: date | None = None,
    skip: int = 0,
    limit: int = 50,
) -> list[PemindahanResponse]:
    rows = await pemindahan_repository.get_all(
        db, spbu_id, tanggal_mulai=tanggal_mulai, tanggal_akhir=tanggal_akhir, skip=skip, limit=limit
    )
    return [_to_response(r) for r in rows]


async def get_pemindahan(db: AsyncSession, spbu_id: int, pemindahan_id: int) -> PemindahanResponse:
    row = await pemindahan_repository.get_by_id(db, spbu_id, pemindahan_id)
    if not row:
        raise ValueError("Pemindahan tidak ditemukan")
    return _to_response(row)


async def create_pemindahan(
    db: AsyncSession,
    spbu_id: int,
    data: PemindahanCreate,
    user_id: int,
) -> PemindahanResponse:
    if data.tangki_sumber_id == data.tangki_tujuan_id:
        raise ValueError("Tangki sumber dan tujuan tidak boleh sama")

    volume_masuk = data.volume_tujuan_sesudah - data.volume_tujuan_sebelum
    losses_transfer = data.volume_sumber_sebelum - volume_masuk

    if volume_masuk < 0:
        raise ValueError("Volume tujuan sesudah harus lebih besar dari sebelum")

    row = PemindahanProduk(
        spbu_id=spbu_id,
        tanggal=data.tanggal,
        jam=data.jam,
        tangki_sumber_id=data.tangki_sumber_id,
        tangki_tujuan_id=data.tangki_tujuan_id,
        volume_sumber_sebelum=data.volume_sumber_sebelum,
        volume_tujuan_sebelum=data.volume_tujuan_sebelum,
        volume_tujuan_sesudah=data.volume_tujuan_sesudah,
        volume_masuk=volume_masuk,
        losses_transfer=losses_transfer,
        catatan=data.catatan,
        dilakukan_oleh=user_id,
    )

    # Set produk_lama from tangki_sumber's current produk
    from app.models.spbu import Tangki
    from sqlalchemy import select
    tangki_result = await db.execute(select(Tangki).where(Tangki.id == data.tangki_sumber_id))
    tangki_sumber = tangki_result.scalar_one_or_none()
    if tangki_sumber:
        row.produk_lama_id = tangki_sumber.produk_id

    try:
        row = await pemindahan_repository.create(db, row)

        from app.utils.audit import log_action
        await log_action(
            db, user_id=user_id, spbu_id=spbu_id, aksi="pemindahan", modul="tangki",
            object_id=row.id, detail={"tangki_sumber": data.tangki_sumber_id, "tangki_tujuan": data.tangki_tujuan_id},
        )

        await db.commit()
        await db.refresh(row, attribute_names=["tangki_sumber", "tangki_tujuan", "produk_lama", "user"])
    except IntegrityError:
        await db.rollback()
        raise ValueError("Data pemindahan konflik atau sudah ada")
    except SQLAlchemyError:
        await db.rollback()
        raise
    return _to_response(row)
