from datetime import date, time
from decimal import Decimal
from typing import Literal

from pydantic import BaseModel, ConfigDict


class ShiftBase(BaseModel):
    nama: str
    jam_mulai: time
    jam_selesai: time
    is_active: bool = True


class ShiftCreate(ShiftBase):
    pass


class ShiftUpdate(BaseModel):
    nama: str | None = None
    jam_mulai: time | None = None
    jam_selesai: time | None = None
    is_active: bool | None = None


class ShiftResponse(ShiftBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    spbu_id: int


class SpbuBase(BaseModel):
    name: str
    nomor_pertamina: str
    kode_internal: str | None = None
    alamat: str | None = None
    no_telepon: str | None = None
    nama_bank: str | None = None
    no_rekening: str | None = None
    atas_nama: str | None = None
    teller_discrepancy_threshold_pct: Decimal = Decimal("0.300")


class SpbuCreate(SpbuBase):
    shifts: list[ShiftCreate] = []


class SpbuUpdate(BaseModel):
    name: str | None = None
    nomor_pertamina: str | None = None
    kode_internal: str | None = None
    alamat: str | None = None
    no_telepon: str | None = None
    nama_bank: str | None = None
    no_rekening: str | None = None
    atas_nama: str | None = None
    teller_discrepancy_threshold_pct: Decimal | None = None
    is_active: bool | None = None


class SpbuResponse(SpbuBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    is_active: bool
    shifts: list[ShiftResponse] = []


# --- Island ---
class IslandBase(BaseModel):
    nama: str
    urutan: int = 1
    is_active: bool = True


class IslandCreate(IslandBase):
    pass


class IslandUpdate(BaseModel):
    nama: str | None = None
    urutan: int | None = None
    is_active: bool | None = None


class NozzleResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    island_id: int
    nama: str
    produk_id: int | None
    tangki_id: int | None
    primary_teller: str
    is_active: bool
    produk_nama: str | None = None
    tangki_nama: str | None = None

    @classmethod
    def from_orm_with_names(cls, nozzle) -> "NozzleResponse":
        return cls(
            id=nozzle.id,
            island_id=nozzle.island_id,
            nama=nozzle.nama,
            produk_id=nozzle.produk_id,
            tangki_id=nozzle.tangki_id,
            primary_teller=nozzle.primary_teller,
            is_active=nozzle.is_active,
            produk_nama=nozzle.produk.nama if nozzle.produk else None,
            tangki_nama=nozzle.tangki.nama if nozzle.tangki else None,
        )


class IslandResponse(IslandBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    spbu_id: int
    nozzles: list[NozzleResponse] = []


# --- Nozzle ---
class NozzleCreate(BaseModel):
    nama: str
    produk_id: int | None = None
    tangki_id: int | None = None
    is_active: bool = True


class NozzleUpdate(BaseModel):
    nama: str | None = None
    produk_id: int | None = None
    tangki_id: int | None = None
    primary_teller: Literal["manual", "digital"] | None = None
    is_active: bool | None = None


# --- Tangki ---
class KalibrasiTangkiItem(BaseModel):
    tinggi_mm: Decimal
    volume_liter: Decimal


class KalibrasiTangkiResponse(KalibrasiTangkiItem):
    model_config = ConfigDict(from_attributes=True)
    id: int
    tangki_id: int


class TangkiBase(BaseModel):
    nama: str
    kode_kalibrasi: str | None = None
    kapasitas_liter: Decimal
    produk_id: int | None = None
    is_active: bool = True


class TangkiCreate(TangkiBase):
    pass


class TangkiUpdate(BaseModel):
    nama: str | None = None
    kode_kalibrasi: str | None = None
    kapasitas_liter: Decimal | None = None
    produk_id: int | None = None
    is_active: bool | None = None


class TangkiResponse(TangkiBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    spbu_id: int
    kalibrasi: list[KalibrasiTangkiResponse] = []
    produk_nama: str | None = None

    @classmethod
    def from_orm_with_names(cls, tangki) -> "TangkiResponse":
        return cls(
            id=tangki.id,
            spbu_id=tangki.spbu_id,
            nama=tangki.nama,
            kode_kalibrasi=tangki.kode_kalibrasi,
            kapasitas_liter=tangki.kapasitas_liter,
            produk_id=tangki.produk_id,
            is_active=tangki.is_active,
            kalibrasi=[KalibrasiTangkiResponse.model_validate(k) for k in tangki.kalibrasi],
            produk_nama=tangki.produk.nama if tangki.produk else None,
        )


# --- Tenant & Kontrak ---
class TenantBase(BaseModel):
    nama: str
    jenis_usaha: str | None = None
    luas_m2: Decimal | None = None
    kontak: str | None = None
    is_active: bool = True


class TenantCreate(TenantBase):
    pass


class TenantUpdate(BaseModel):
    nama: str | None = None
    jenis_usaha: str | None = None
    luas_m2: Decimal | None = None
    kontak: str | None = None
    is_active: bool | None = None


class KontrakSewaBase(BaseModel):
    nilai_bulanan: Decimal
    tanggal_mulai: date
    tanggal_akhir: date
    dokumen_url: str | None = None


class KontrakSewaCreate(KontrakSewaBase):
    pass


class KontrakSewaUpdate(BaseModel):
    nilai_bulanan: Decimal | None = None
    tanggal_mulai: date | None = None
    tanggal_akhir: date | None = None
    status: str | None = None
    dokumen_url: str | None = None


class KontrakSewaResponse(KontrakSewaBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    tenant_id: int
    status: str


class TenantResponse(TenantBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    spbu_id: int
    kontrak: list[KontrakSewaResponse] = []
