from pydantic import BaseModel, ConfigDict, Field, model_validator
from datetime import date, datetime
from typing import Optional, List, Dict, Any


class ManufacturingCostBase(BaseModel):
    product_id: str
    date: date
    batch_size: float = Field(..., description="Quantity produced in this batch")
    batch_number: Optional[str] = None
    material_cost: Optional[float] = 0.0
    labor_cost: Optional[float] = 0.0
    overhead_cost: Optional[float] = 0.0
    notes: Optional[str] = None
    production_order_id: Optional[str] = None

    # Backward compatibility for clients sending quantity
    quantity: Optional[float] = None

    @model_validator(mode="before")
    @classmethod
    def map_quantity_alias(cls, data):
        if isinstance(data, dict):
            if data.get("quantity") is not None and not data.get("batch_size"):
                data["batch_size"] = data["quantity"]
        return data


class ManufacturingCostCreate(ManufacturingCostBase):
    pass


class ManufacturingCostUpdate(BaseModel):
    product_id: Optional[str] = None
    date: Optional[date] = None
    batch_size: Optional[float] = None
    quantity: Optional[float] = None
    batch_number: Optional[str] = None
    material_cost: Optional[float] = None
    labor_cost: Optional[float] = None
    overhead_cost: Optional[float] = None
    notes: Optional[str] = None
    production_order_id: Optional[str] = None


class ManufacturingCost(ManufacturingCostBase):
    id: int
    total_cost: float
    unit_cost: float
    status: Optional[str] = "draft"
    product_name: Optional[str] = None
    product_sku: Optional[str] = None

    model_config = ConfigDict(from_attributes=True)


class ManufacturingTotals(BaseModel):
    total_materials: float
    total_labor: float
    total_overhead: float
    total_manufacturing: float
    total_batches: int
    total_intangible: float
    total_wip: float


class ProductTypeDistribution(BaseModel):
    type: str
    count: int
    total_cost: float


class MonthlyTrend(BaseModel):
    month: str
    materials: float
    labor: float
    overhead: float
    total: float


class ManufacturingStats(BaseModel):
    totals: ManufacturingTotals
    product_type_distribution: List[ProductTypeDistribution]
    monthly_trends: List[MonthlyTrend]


class ProductionOrderCreate(BaseModel):
    product_id: str
    quantity_planned: float
    recipe_id: Optional[str] = None
    manufacturing_branch_id: Optional[str] = None
    cost_center_id: Optional[str] = None
    project_id: Optional[str] = None
    department_id: Optional[str] = None
    labor_cost: float = 0.0
    overhead_cost: float = 0.0
    notes: Optional[str] = None
    post_to_gl: bool = True


class ProductionOrderResponse(BaseModel):
    id: str
    order_number: str
    product_id: str
    product_name: Optional[str] = None
    quantity_planned: float
    quantity_produced: float
    status: str
    total_material_cost: float
    total_labor_cost: float
    total_overhead_cost: float
    total_cost: float
    unit_cost: float
    posting_status: str
    batch_number: Optional[str] = None
    manufacturing_cost_id: Optional[int] = None

    model_config = ConfigDict(from_attributes=True)


class ProduceToHQRequest(BaseModel):
    product_id: str
    quantity: int
    labor_cost: float = 0.0
    overhead_cost: float = 0.0
    created_by: Optional[str] = None
    notes: Optional[str] = None
    post_to_gl: bool = True
    cost_center_id: Optional[str] = None
    project_id: Optional[str] = None
    department_id: Optional[str] = None
