from pydantic import BaseModel, Field, condecimal
from typing import List, Optional, Union
from uuid import UUID
from datetime import date, datetime
from decimal import Decimal


# ─── ASSET ────────────────────────────────────────────────────────────────────

class MaintenanceAssetCreate(BaseModel):
    name: str
    machine_number: Optional[int] = None
    machine_type: Optional[str] = None
    year_of_commissioning: Optional[int] = None
    location: Optional[str] = None
    is_active: bool = True


class MaintenanceAssetUpdate(BaseModel):
    name: Optional[str] = None
    machine_number: Optional[int] = None
    machine_type: Optional[str] = None
    year_of_commissioning: Optional[int] = None
    location: Optional[str] = None
    is_active: Optional[bool] = None


class MaintenanceAssetOut(BaseModel):
    id: UUID
    name: str
    machine_number: Optional[int]
    machine_type: Optional[str]
    year_of_commissioning: Optional[int]
    location: Optional[str]
    is_active: bool
    created_at: datetime

    model_config = {"from_attributes": True}


# ─── CHECKLIST ITEM ───────────────────────────────────────────────────────────

class ChecklistItemCreate(BaseModel):
    machine_type: str
    sr_no: Optional[int] = None
    check_point: str
    specification: Optional[str] = None
    is_active: bool = True


class ChecklistItemUpdate(BaseModel):
    machine_type: Optional[str] = None
    sr_no: Optional[int] = None
    check_point: Optional[str] = None
    specification: Optional[str] = None
    is_active: Optional[bool] = None

class ChecklistItemOut(BaseModel):
    id: UUID
    machine_type: str
    sr_no: Optional[int]
    check_point: str
    specification: Optional[str]
    is_active: bool

    model_config = {"from_attributes": True}


# ─── RECORD ACTION ────────────────────────────────────────────────────────────

class RecordActionCreate(BaseModel):
    sr_no: Optional[int] = None
    action_taken: str
    is_ok: bool = False


class RecordActionOut(BaseModel):
    id: UUID
    sr_no: Optional[int]
    action_taken: str
    is_ok: bool

    model_config = {"from_attributes": True}


# ─── MAINTENANCE RECORD ───────────────────────────────────────────────────────

class MaintenanceRecordCreate(BaseModel):
    asset_id: UUID
    record_date: date
    maintenance_type: str = "PM"         # PM or BD
    status: str = "OPEN"                 # OPEN, IN_PROGRESS, COMPLETED, CLOSED
    priority: str = "MEDIUM"             # CRITICAL, HIGH, MEDIUM, LOW
    assigned_technician: Optional[str] = None
    estimated_time: Optional[str] = None
    problem_faced: Optional[str] = None
    root_cause: Optional[str] = None
    material_used: Optional[str] = None
    material_cost: Optional[Decimal] = None
    time_taken: Optional[str] = None
    supervisor_name: Optional[str] = None
    remarks: Optional[str] = None
    photo_url: Optional[str] = None
    actions: List[RecordActionCreate] = []


class MaintenanceRecordUpdate(BaseModel):
    record_date: Optional[date] = None
    maintenance_type: Optional[str] = None
    status: Optional[str] = None
    priority: Optional[str] = None
    assigned_technician: Optional[str] = None
    estimated_time: Optional[str] = None
    problem_faced: Optional[str] = None
    root_cause: Optional[str] = None
    material_used: Optional[str] = None
    material_cost: Optional[Decimal] = None
    time_taken: Optional[str] = None
    supervisor_name: Optional[str] = None
    remarks: Optional[str] = None
    photo_url: Optional[str] = None
    actions: Optional[List[Union[RecordActionCreate, dict]]] = None


class MaintenanceRecordOut(BaseModel):
    id: UUID
    asset_id: UUID
    wo_number: Optional[str]
    record_date: date
    maintenance_type: str
    status: str
    priority: str
    assigned_technician: Optional[str]
    estimated_time: Optional[str]
    problem_faced: Optional[str]
    root_cause: Optional[str]
    material_used: Optional[str]
    material_cost: Optional[Decimal]
    time_taken: Optional[str]
    supervisor_name: Optional[str]
    remarks: Optional[str]
    photo_url: Optional[str]
    created_at: datetime
    actions: List[RecordActionOut] = []

    model_config = {"from_attributes": True}


class MaintenanceRecordListOut(BaseModel):
    """Lean version for list view (no nested actions)"""
    id: UUID
    asset_id: UUID
    wo_number: Optional[str]
    record_date: date
    maintenance_type: str
    status: str
    priority: str
    assigned_technician: Optional[str]
    problem_faced: Optional[str]
    time_taken: Optional[str]
    supervisor_name: Optional[str]
    created_at: datetime

    model_config = {"from_attributes": True}


# ─── PM SCHEDULE ─────────────────────────────────────────────────────────────

class PMScheduleCreate(BaseModel):
    asset_id: UUID
    scheduled_date: date
    year: int
    month: int
    status: str = "PLANNED"
    notes: Optional[str] = None


class PMScheduleUpdate(BaseModel):
    status: Optional[str] = None
    completed_date: Optional[date] = None
    notes: Optional[str] = None


class PMScheduleOut(BaseModel):
    id: UUID
    asset_id: UUID
    scheduled_date: date
    year: int
    month: int
    status: str
    completed_date: Optional[date]
    notes: Optional[str]
    asset: Optional[MaintenanceAssetOut] = None

    model_config = {"from_attributes": True}


# ─── DASHBOARD ────────────────────────────────────────────────────────────────

class MaintenanceDashboardStats(BaseModel):
    total_assets: int
    active_assets: int
    pm_this_month: int
    bd_this_month: int
    total_records: int
    planned_this_month: int
    done_this_month: int
    overdue_count: int
    incoming_material_entries: int
    monthly_stock_entries: int
    equipment_purchase_entries: int
    equipment_rental_entries: int


# ─── INCOMING MATERIAL ────────────────────────────────────────────────────────

class IncomingMaterialCreate(BaseModel):
    entry_date: date
    vendor: Optional[str] = None
    category: Optional[str] = None
    material_name: str
    quantity: Decimal
    rate: Optional[Decimal] = None
    bill_no: Optional[str] = None
    discount: Optional[Decimal] = None
    challan_no: Optional[str] = None
    remarks: Optional[str] = None
    asset_id: Optional[UUID] = None  # Optional machine linkage
    bill_photo_url: Optional[str] = None


class IncomingMaterialUpdate(BaseModel):
    entry_date: Optional[date] = None
    vendor: Optional[str] = None
    category: Optional[str] = None
    material_name: Optional[str] = None
    quantity: Optional[Decimal] = None
    rate: Optional[Decimal] = None
    bill_no: Optional[str] = None
    discount: Optional[Decimal] = None
    challan_no: Optional[str] = None
    remarks: Optional[str] = None
    asset_id: Optional[UUID] = None  # Optional machine linkage
    bill_photo_url: Optional[str] = None


class IncomingMaterialOut(BaseModel):
    id: UUID
    entry_date: date
    vendor: Optional[str]
    category: Optional[str]
    material_name: str
    quantity: Decimal
    rate: Optional[Decimal]
    total_amount: Optional[Decimal]
    bill_no: Optional[str]
    discount: Optional[Decimal]
    challan_no: Optional[str]
    remarks: Optional[str]
    asset_id: Optional[UUID]  # Optional machine linkage
    bill_photo_url: Optional[str]
    created_at: datetime

    model_config = {"from_attributes": True}


# ─── DIESEL RECORD ────────────────────────────────────────────────────────────

class DieselRecordCreate(BaseModel):
    entry_date: date
    dg_set_no: str
    diesel_ltr: Decimal
    oil_ltr: Optional[Decimal] = None


class DieselRecordUpdate(BaseModel):
    entry_date: Optional[date] = None
    dg_set_no: Optional[str] = None
    diesel_ltr: Optional[Decimal] = None
    oil_ltr: Optional[Decimal] = None


class DieselRecordOut(BaseModel):
    id: UUID
    entry_date: date
    dg_set_no: str
    diesel_ltr: Decimal
    oil_ltr: Optional[Decimal]
    created_at: datetime

    model_config = {"from_attributes": True}


# ─── LPG GAS RECORD ───────────────────────────────────────────────────────────

class LPGGasRecordCreate(BaseModel):
    entry_date: date
    gas_name: str
    quantity: int
    kg: Decimal
    price: Optional[Decimal] = None
    bill_no: Optional[str] = None


class LPGGasRecordUpdate(BaseModel):
    entry_date: Optional[date] = None
    gas_name: Optional[str] = None
    quantity: Optional[int] = None
    kg: Optional[Decimal] = None
    price: Optional[Decimal] = None
    bill_no: Optional[str] = None


class LPGGasRecordOut(BaseModel):
    id: UUID
    entry_date: date
    gas_name: str
    quantity: int
    kg: Decimal
    price: Optional[Decimal]
    total_amount: Optional[Decimal]
    bill_no: Optional[str]
    created_at: datetime

    model_config = {"from_attributes": True}


# ─── SOLAR MAINTENANCE ────────────────────────────────────────────────────────

class SolarMaintenanceCreate(BaseModel):
    entry_date: date
    part_name: str
    quantity: Decimal
    price: Decimal
    bill_no: Optional[str] = None


class SolarMaintenanceUpdate(BaseModel):
    entry_date: Optional[date] = None
    part_name: Optional[str] = None
    quantity: Optional[Decimal] = None
    price: Optional[Decimal] = None
    bill_no: Optional[str] = None


class SolarMaintenanceOut(BaseModel):
    id: UUID
    entry_date: date
    part_name: str
    quantity: Decimal
    price: Decimal
    total_amount: Decimal
    bill_no: Optional[str]
    created_at: datetime

    model_config = {"from_attributes": True}


# ── Monthly Stock ─────────────────────────────────────────────────────────────

class MonthlyStockBase(BaseModel):
    stock_month: int = Field(ge=1, le=12)
    stock_year: int
    category: str
    material_name: str
    uom: str
    cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    opening_qty: condecimal(max_digits=12, decimal_places=3) = Decimal('0.000')
    incoming_qty: condecimal(max_digits=12, decimal_places=3) = Decimal('0.000')
    consumption_qty: condecimal(max_digits=12, decimal_places=3) = Decimal('0.000')


class MonthlyStockCreate(MonthlyStockBase):
    pass


class MonthlyStockUpdate(BaseModel):
    cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    opening_qty: Optional[condecimal(max_digits=12, decimal_places=3)] = None
    incoming_qty: Optional[condecimal(max_digits=12, decimal_places=3)] = None
    consumption_qty: Optional[condecimal(max_digits=12, decimal_places=3)] = None


class MonthlyStockOut(MonthlyStockBase):
    id: UUID
    category_order: int = 0
    opening_amount: Decimal
    incoming_amount: Decimal
    total_qty: Decimal
    total_amount: Decimal
    consumption_amount: Decimal
    closing_qty: Decimal
    closing_amount: Decimal
    created_at: datetime
    updated_at: Optional[datetime]

    class Config:
        from_attributes = True


class MonthlySummaryOut(BaseModel):
    year: int
    month: int
    material_type: str
    total_received: Decimal
    total_consumed: Decimal
    avg_daily_consumption: Optional[Decimal]
    opening_stock: Decimal
    closing_stock: Decimal


# ─── EQUIPMENT PURCHASE ───────────────────────────────────────────────────────

class EquipmentPurchaseCreate(BaseModel):
    purchase_month: int
    purchase_year: int
    equipment_name: str
    quantity: Decimal
    unit_price: Decimal
    remarks: Optional[str] = None
    # total_amount = quantity × unit_price (auto)


class EquipmentPurchaseUpdate(BaseModel):
    equipment_name: Optional[str] = None
    quantity: Optional[Decimal] = None
    unit_price: Optional[Decimal] = None
    remarks: Optional[str] = None


class EquipmentPurchaseOut(BaseModel):
    id: UUID
    purchase_month: int
    purchase_year: int
    equipment_name: str
    quantity: Decimal
    unit_price: Decimal
    total_amount: Decimal
    remarks: Optional[str]
    created_at: datetime

    model_config = {"from_attributes": True}


# ─── EQUIPMENT RENTAL ────────────────────────────────────────────────────────

class EquipmentRentalCreate(BaseModel):
    rental_date: date
    vendor: str
    equipment_type: str
    in_time: Optional[str] = None
    out_time: Optional[str] = None
    hours: Optional[Decimal] = None
    work_description: Optional[str] = None
    bill_no: Optional[str] = None
    amount: Optional[Decimal] = None


class EquipmentRentalUpdate(BaseModel):
    rental_date: Optional[date] = None
    vendor: Optional[str] = None
    equipment_type: Optional[str] = None
    in_time: Optional[str] = None
    out_time: Optional[str] = None
    hours: Optional[Decimal] = None
    work_description: Optional[str] = None
    bill_no: Optional[str] = None
    amount: Optional[Decimal] = None


class EquipmentRentalOut(BaseModel):
    id: UUID
    rental_date: date
    vendor: str
    equipment_type: str
    in_time: Optional[str]
    out_time: Optional[str]
    hours: Optional[Decimal]
    work_description: Optional[str]
    bill_no: Optional[str]
    amount: Optional[Decimal]
    created_at: datetime

    model_config = {"from_attributes": True}


# ─── MACHINE CONSUMPTION COST ────────────────────────────────────────────────

class MachineCostBase(BaseModel):
    machine_name: str
    display_order: int = 0
    year: int
    jan_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    feb_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    mar_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    apr_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    may_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    jun_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    jul_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    aug_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    sep_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    oct_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    nov_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')
    dec_cost: condecimal(max_digits=12, decimal_places=2) = Decimal('0.00')


class MachineCostCreate(MachineCostBase):
    pass


class MachineCostUpdate(BaseModel):
    machine_name: Optional[str] = None
    display_order: Optional[int] = None
    jan_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    feb_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    mar_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    apr_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    may_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    jun_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    jul_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    aug_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    sep_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    oct_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    nov_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None
    dec_cost: Optional[condecimal(max_digits=12, decimal_places=2)] = None


class MachineCostOut(MachineCostBase):
    id: UUID
    created_at: datetime
    updated_at: Optional[datetime]

    model_config = {"from_attributes": True}


# ─── DAILY CONSUMABLES (GAS & WIRE) ──────────────────────────────────────────

class DailyConsumableStockBase(BaseModel):
    record_date: date
    consumable_type: str
    opening_stock: condecimal(max_digits=10, decimal_places=2) = Decimal('0.00')
    received_stock: condecimal(max_digits=10, decimal_places=2) = Decimal('0.00')
    total_stock: condecimal(max_digits=10, decimal_places=2) = Decimal('0.00')
    consumed_stock: condecimal(max_digits=10, decimal_places=2) = Decimal('0.00')
    closing_stock: condecimal(max_digits=10, decimal_places=2) = Decimal('0.00')
    remark: Optional[str] = None


class DailyConsumableStockCreate(DailyConsumableStockBase):
    pass


class DailyConsumableStockUpdate(BaseModel):
    opening_stock: Optional[condecimal(max_digits=10, decimal_places=2)] = None
    received_stock: Optional[condecimal(max_digits=10, decimal_places=2)] = None
    total_stock: Optional[condecimal(max_digits=10, decimal_places=2)] = None
    consumed_stock: Optional[condecimal(max_digits=10, decimal_places=2)] = None
    closing_stock: Optional[condecimal(max_digits=10, decimal_places=2)] = None
    remark: Optional[str] = None


class DailyConsumableStockOut(DailyConsumableStockBase):
    id: UUID
    created_at: datetime
    updated_at: Optional[datetime]

    model_config = {"from_attributes": True}

class DailyConsumableBatchUpdateItem(BaseModel):
    record_date: date
    consumable_type: str
    received_stock: condecimal(max_digits=10, decimal_places=2) = Decimal('0.00')
    consumed_stock: condecimal(max_digits=10, decimal_places=2) = Decimal('0.00')
    remark: Optional[str] = None

class DailyConsumableBatchUpdateReq(BaseModel):
    year: int
    month: int
    consumable_type: str
    initial_opening_stock: condecimal(max_digits=10, decimal_places=2)
    days_data: List[DailyConsumableBatchUpdateItem]


# ─── COST VS PRODUCTION ANALYTICS ────────────────────────────────────────────

class MachineCostVsProductionItem(BaseModel):
    """One row in the cost-vs-production analytics table."""
    machine_name: str
    month_cost: Decimal              # Maintenance spend for this machine in the selected month
    buses_produced: int              # Buses dispatched in the selected month (from chassis_master)
    cost_per_bus: Optional[Decimal]  # month_cost / buses_produced (None if 0 buses)
    alert_level: str                 # "OK" | "WATCH" | "ALERT"
    alert_message: Optional[str]     # Human-readable flag message


class CostVsProductionOut(BaseModel):
    year: int
    month: int
    month_name: str
    total_buses_produced: int
    total_maintenance_cost: Decimal
    overall_cost_per_bus: Optional[Decimal]
    machines: List[MachineCostVsProductionItem]

