"""PB (Permintaan Barang) schemas."""

from datetime import datetime
from decimal import Decimal

from pydantic import BaseModel, field_validator, model_validator


# ── Project ───────────────────────────────────────────────────────────────────

class ProjectCreate(BaseModel):
    nama: str
    deskripsi: str | None = None


class ProjectUpdate(BaseModel):
    nama: str | None = None
    deskripsi: str | None = None
    is_closed: bool | None = None


class ProjectResponse(BaseModel):
    id: int
    spbu_id: int
    nama: str
    deskripsi: str | None
    is_closed: bool

    model_config = {"from_attributes": True}


# ── PB Item ───────────────────────────────────────────────────────────────────

class PBItemCreate(BaseModel):
    urutan: int = 0
    nama_item: str
    qty_requested: Decimal
    satuan: str
    harga_satuan: Decimal

    @field_validator("qty_requested", "harga_satuan")
    @classmethod
    def must_be_positive(cls, v: Decimal) -> Decimal:
        if v <= 0:
            raise ValueError("Harus lebih dari 0")
        return v


class PBItemUpdate(BaseModel):
    urutan: int | None = None
    nama_item: str | None = None
    qty_requested: Decimal | None = None
    satuan: str | None = None
    harga_satuan: Decimal | None = None


class PBItemHeadReview(BaseModel):
    status: str  # "approved" | "rejected"
    qty_approved: Decimal | None = None
    catatan_head: str | None = None

    @model_validator(mode="after")
    def check_qty_when_approved(self) -> "PBItemHeadReview":
        if self.status == "approved" and self.qty_approved is None:
            raise ValueError("qty_approved wajib diisi saat approve")
        return self


class PBItemResponse(BaseModel):
    id: int
    pb_id: int
    urutan: int
    nama_item: str
    qty_requested: Decimal
    satuan: str
    harga_satuan: Decimal
    total_estimasi: Decimal
    status: str
    qty_approved: Decimal | None
    catatan_head: str | None

    model_config = {"from_attributes": True}

    @classmethod
    def from_orm_item(cls, item) -> "PBItemResponse":
        return cls(
            id=item.id,
            pb_id=item.pb_id,
            urutan=item.urutan,
            nama_item=item.nama_item,
            qty_requested=item.qty_requested,
            satuan=item.satuan,
            harga_satuan=item.harga_satuan,
            total_estimasi=item.qty_requested * item.harga_satuan,
            status=item.status if isinstance(item.status, str) else item.status.value,
            qty_approved=item.qty_approved,
            catatan_head=item.catatan_head,
        )


# ── PB ────────────────────────────────────────────────────────────────────────

class PBCreate(BaseModel):
    judul: str
    deskripsi: str | None = None
    project_id: int | None = None
    is_kas_kecil: bool = False
    items: list[PBItemCreate] = []


class PBUpdate(BaseModel):
    judul: str | None = None
    deskripsi: str | None = None
    project_id: int | None = None
    is_kas_kecil: bool | None = None
    items: list[PBItemCreate] | None = None  # full replace when provided


class PBForwardBody(BaseModel):
    pass  # no body needed, manager just forwards


class PBHeadReviewBody(BaseModel):
    catatan_head: str | None = None
    items: list[dict]  # [{id, status, qty_approved?, catatan_head?}]


class PBResponse(BaseModel):
    id: int
    spbu_id: int
    nomor: str
    judul: str
    deskripsi: str | None
    project_id: int | None
    project_nama: str | None
    is_kas_kecil: bool
    status: str
    attachment_url: str | None

    # Budget summary
    total_estimasi: Decimal
    total_approved: Decimal
    total_realisasi: Decimal

    created_by_name: str | None
    submitted_at: datetime | None
    forwarded_by_name: str | None
    forwarded_at: datetime | None
    recalled_by_name: str | None
    recalled_at: datetime | None
    reviewed_by_name: str | None
    reviewed_at: datetime | None
    catatan_head: str | None
    created_at: datetime

    items: list[PBItemResponse] = []

    model_config = {"from_attributes": True}


# ── Ledger ────────────────────────────────────────────────────────────────────

class LedgerEntry(BaseModel):
    tanggal: str
    keterangan: str
    debit: Decimal
    kredit: Decimal
    saldo: Decimal
    ref_type: str   # "alokasi" | "expense"
    ref_id: int


class PBLedgerResponse(BaseModel):
    pb_id: int
    nomor: str
    judul: str
    total_approved: Decimal
    total_realisasi: Decimal
    sisa: Decimal
    entries: list[LedgerEntry]
