"""Anomali service — business logic for anomaly detection and management."""

from __future__ import annotations

from datetime import datetime, timezone

from app.models.anomali import AnomaliRecord, StatusAnomali
from app.repositories import anomali_repository
from app.schemas.anomali import AnomaliCreate, AnomaliResponse, AnomaliResolve, AnomaliUpdate
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession


def _build_response(r: AnomaliRecord) -> AnomaliResponse:
    return AnomaliResponse(
        id=r.id,
        spbu_id=r.spbu_id,
        kode=r.tipe,
        tipe=r.tipe,
        laporan_shift_id=r.laporan_shift_id,
        produk_id=r.produk_id,
        produk_nama=r.produk.nama if r.produk else None,
        nozzle_id=r.nozzle_id,
        nozzle_nama=r.nozzle.nama if r.nozzle else None,
        plat_nomor=r.plat_nomor,
        deskripsi=r.deskripsi,
        detail=r.detail,
        status=r.status,
        resolved_at=r.resolved_at,
        resolved_by_id=r.resolved_by_id,
        catatan_resolusi=r.catatan_resolusi,
        assigned_to=r.assigned_to,
        assigned_to_name=r.assigned_user.name if r.assigned_user else None,
        notes=r.notes,
        created_at=r.created_at,
        updated_at=r.updated_at,
    )


async def list_anomali(
    db: AsyncSession,
    spbu_id: int,
    tipe: str | None = None,
    status: str | None = None,
    skip: int = 0,
    limit: int = 50,
) -> tuple[list[AnomaliResponse], int]:
    rows, total = await anomali_repository.get_all(
        db, spbu_id, tipe=tipe, status=status, skip=skip, limit=limit
    )
    return [_build_response(r) for r in rows], total


async def get_anomali(
    db: AsyncSession, spbu_id: int, anomali_id: int
) -> AnomaliResponse:
    record = await anomali_repository.get_by_id(db, anomali_id, spbu_id)
    if record is None:
        raise ValueError("Anomali tidak ditemukan")
    return _build_response(record)


async def create_anomali(
    db: AsyncSession, spbu_id: int, data: AnomaliCreate
) -> AnomaliResponse:
    try:
        record = await anomali_repository.create(db, {
            "spbu_id": spbu_id,
            "tipe": data.tipe,
            "produk_id": data.produk_id,
            "nozzle_id": data.nozzle_id,
            "plat_nomor": data.plat_nomor,
            "detail": data.detail,
            "status": StatusAnomali.NEW,
        })
        await db.commit()
    except IntegrityError:
        await db.rollback()
        raise ValueError("Data anomali konflik atau sudah ada")
    except SQLAlchemyError:
        await db.rollback()
        raise
    return _build_response(record)


async def update_anomali(
    db: AsyncSession, spbu_id: int, anomali_id: int, data: AnomaliUpdate
) -> AnomaliResponse:
    record = await anomali_repository.get_by_id(db, anomali_id, spbu_id)
    if record is None:
        raise ValueError("Anomali tidak ditemukan")

    update_data = data.model_dump(exclude_unset=True)
    if not update_data:
        raise ValueError("Tidak ada data yang diupdate")

    try:
        updated = await anomali_repository.update(db, record, update_data)
        await db.commit()
    except SQLAlchemyError:
        await db.rollback()
        raise
    return _build_response(updated)


async def resolve_anomali(
    db: AsyncSession, spbu_id: int, anomali_id: int, data: AnomaliResolve, resolved_by_id: int
) -> AnomaliResponse:
    """Transition anomali to closed_valid or false_positive with audit fields."""
    valid_statuses = {StatusAnomali.CLOSED_VALID.value, StatusAnomali.FALSE_POSITIVE.value}
    if data.status not in valid_statuses:
        raise ValueError(f"Status resolve harus salah satu dari: {', '.join(valid_statuses)}")

    record = await anomali_repository.get_by_id(db, anomali_id, spbu_id)
    if record is None:
        raise ValueError("Anomali tidak ditemukan")
    if record.status in (StatusAnomali.CLOSED_VALID.value, StatusAnomali.FALSE_POSITIVE.value):
        raise ValueError("Anomali sudah diresolve")

    try:
        updated = await anomali_repository.update(db, record, {
            "status": data.status,
            "catatan_resolusi": data.catatan_resolusi,
            "resolved_by_id": resolved_by_id,
            "resolved_at": datetime.now(timezone.utc),
        })
        await db.commit()
    except SQLAlchemyError:
        await db.rollback()
        raise
    return _build_response(updated)


async def count_active(db: AsyncSession, spbu_id: int) -> int:
    return await anomali_repository.count_active(db, spbu_id)
