from datetime import date, datetime
from decimal import Decimal

from pydantic import BaseModel, Field

from app.domain.enums import (
    AmountType,
    DepartmentIssuePriority,
    DepartmentIssueReason,
    DepartmentIssueStatus,
    DepartmentIssueType,
    DepartmentStatus,
    InventoryTxnDirection,
    InventoryTxnType,
    ItemTransactionReferenceType,
    ItemTransactionStatus,
    LowStockAlertTarget,
    PricingModel,
    StockReportBasis,
    StockReportStatus,
    StockTransferPriority,
    StockTransferReason,
    StockTransferStatus,
    UnitKind,
    WarehousePriority,
    WarehouseStatus,
    WarehouseType,
)


class ItemCategoryCreate(BaseModel):
    code: str = Field(..., min_length=1, max_length=30)
    name: str = Field(..., min_length=1, max_length=200)
    description: str | None = None
    is_active: bool = True


class ItemCategoryUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=200)
    description: str | None = None
    is_active: bool | None = None


class ItemCategoryResponse(BaseModel):
    id: str
    company_id: str
    code: str
    name: str
    description: str | None
    is_active: bool
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class ItemTypeCreate(BaseModel):
    code: str = Field(..., min_length=1, max_length=30)
    name: str = Field(..., min_length=1, max_length=200)
    category_id: str | None = None
    description: str | None = None
    is_active: bool = True


class ItemTypeUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=200)
    category_id: str | None = None
    description: str | None = None
    is_active: bool | None = None


class ItemTypeResponse(BaseModel):
    id: str
    company_id: str
    category_id: str | None
    category_code: str | None = None
    category_name: str | None = None
    code: str
    name: str
    description: str | None
    is_active: bool
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class ItemGroupCreate(BaseModel):
    code: str = Field(..., min_length=1, max_length=30, description="Unique group code")
    name: str = Field(..., min_length=1, max_length=200, description="Group name")
    category_id: str = Field(..., min_length=1, description="Item category ID")
    item_type_id: str = Field(..., min_length=1, description="Item type ID")
    description: str = Field(..., min_length=1, max_length=255)
    is_active: bool = Field(True, description="Status: Active=true / Inactive=false")
    sort_order: int | None = Field(None, ge=0, description="Lower numbers appear first")
    remarks: str | None = Field(None, max_length=255)
    icon: str | None = Field(
        None, max_length=500, description="Icon path if already uploaded; prefer multipart file"
    )


class ItemGroupUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=200)
    category_id: str | None = Field(None, min_length=1)
    item_type_id: str | None = Field(None, min_length=1)
    description: str | None = Field(None, min_length=1, max_length=255)
    is_active: bool | None = None
    sort_order: int | None = Field(None, ge=0)
    remarks: str | None = Field(None, max_length=255)
    icon: str | None = Field(None, max_length=500)


class ItemGroupResponse(BaseModel):
    id: str
    company_id: str
    category_id: str
    category_code: str | None = None
    category_name: str | None = None
    item_type_id: str
    item_type_code: str | None = None
    item_type_name: str | None = None
    code: str
    name: str
    description: str
    is_active: bool
    sort_order: int | None
    icon: str | None
    remarks: str | None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class BaseUnitCreate(BaseModel):
    code: str = Field(..., min_length=1, max_length=30, description="Unique base unit code")
    name: str = Field(..., min_length=1, max_length=100, description="Base unit name")
    description: str | None = Field(None, max_length=255)
    is_active: bool = Field(True, description="Status: Active=true / Inactive=false")
    sort_order: int | None = Field(None, ge=0, description="Lower numbers appear first")


class BaseUnitUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=100)
    description: str | None = Field(None, max_length=255)
    is_active: bool | None = None
    sort_order: int | None = Field(None, ge=0)


class BaseUnitResponse(BaseModel):
    id: str
    company_id: str
    code: str
    name: str
    description: str | None
    is_active: bool
    sort_order: int | None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class WarehouseCreate(BaseModel):
    code: str = Field(..., min_length=1, max_length=30, description="Unique warehouse code")
    name: str = Field(..., min_length=1, max_length=200, description="Warehouse name")
    warehouse_type: WarehouseType = Field(..., description="Main, Regional, or Branch")
    status: WarehouseStatus = Field(
        WarehouseStatus.ACTIVE,
        description="Use draft for Save as Draft; active/inactive for Save Warehouse",
    )
    priority: WarehousePriority = Field(WarehousePriority.NORMAL)
    parent_warehouse_id: str | None = Field(None, description="Parent warehouse id")
    manager_id: str | None = Field(None, description="User ID of warehouse manager")
    contact_person: str | None = Field(None, max_length=200)
    phone: str | None = Field(None, max_length=30)
    email: str | None = Field(None, max_length=255)
    address_line1: str | None = Field(None, max_length=255, description="Required when status=active")
    address_line2: str | None = Field(None, max_length=255)
    country: str | None = Field(None, max_length=100, description="Required when status=active")
    state_province: str | None = Field(None, max_length=100, description="Required when status=active")
    city: str | None = Field(None, max_length=100, description="Required when status=active")
    postal_code: str | None = Field(None, max_length=30)
    latitude: str | None = Field(None, max_length=30)
    longitude: str | None = Field(None, max_length=30)
    is_active: bool | None = Field(
        None, description="Deprecated — derived from status (active=true)"
    )
    description: str | None = Field(None, max_length=255)
    capacity: str | None = Field(None, max_length=100)
    capacity_uom: str | None = Field(None, max_length=50, description="e.g. sqft, cbm")
    operating_hours: str | None = Field(None, max_length=100, description="e.g. 09:00 AM - 06:00 PM")
    notes: str | None = Field(None, max_length=500)
    remarks: str | None = Field(None, max_length=255)
    allow_stock_in: bool = True
    allow_stock_out: bool = True
    allow_stock_transfer: bool = True
    allow_returns: bool = True
    attachments: list[str] = Field(default_factory=list)


class WarehouseUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=200)
    warehouse_type: WarehouseType | None = None
    status: WarehouseStatus | None = None
    priority: WarehousePriority | None = None
    parent_warehouse_id: str | None = None
    manager_id: str | None = None
    contact_person: str | None = Field(None, max_length=200)
    phone: str | None = Field(None, max_length=30)
    email: str | None = Field(None, max_length=255)
    address_line1: str | None = Field(None, max_length=255)
    address_line2: str | None = Field(None, max_length=255)
    country: str | None = Field(None, max_length=100)
    state_province: str | None = Field(None, max_length=100)
    city: str | None = Field(None, max_length=100)
    postal_code: str | None = Field(None, max_length=30)
    latitude: str | None = Field(None, max_length=30)
    longitude: str | None = Field(None, max_length=30)
    is_active: bool | None = None
    description: str | None = Field(None, max_length=255)
    capacity: str | None = Field(None, max_length=100)
    capacity_uom: str | None = Field(None, max_length=50)
    operating_hours: str | None = Field(None, max_length=100)
    notes: str | None = Field(None, max_length=500)
    remarks: str | None = Field(None, max_length=255)
    allow_stock_in: bool | None = None
    allow_stock_out: bool | None = None
    allow_stock_transfer: bool | None = None
    allow_returns: bool | None = None
    attachments: list[str] | None = None


class WarehouseResponse(BaseModel):
    id: str
    company_id: str
    code: str
    name: str
    warehouse_type: WarehouseType
    status: WarehouseStatus
    priority: WarehousePriority
    parent_warehouse_id: str | None = None
    parent_warehouse_code: str | None = None
    parent_warehouse_name: str | None = None
    manager_id: str | None
    manager_name: str | None = None
    contact_person: str | None = None
    phone: str | None
    email: str | None
    address_line1: str | None = None
    address_line2: str | None = None
    country: str | None = None
    state_province: str | None = None
    city: str | None = None
    postal_code: str | None = None
    latitude: str | None = None
    longitude: str | None = None
    address: str
    location: str
    is_active: bool
    description: str | None
    capacity: str | None
    capacity_uom: str | None = None
    operating_hours: str | None = None
    notes: str | None = None
    remarks: str | None
    allow_stock_in: bool = True
    allow_stock_out: bool = True
    allow_stock_transfer: bool = True
    allow_returns: bool = True
    attachments: list[str] = Field(default_factory=list)
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class BrandCreate(BaseModel):
    code: str | None = Field(
        None,
        min_length=1,
        max_length=30,
        description="Brand code; auto-generated (e.g. BR-001) if omitted",
    )
    name: str = Field(..., min_length=1, max_length=200)
    description: str | None = Field(None, max_length=255)
    logo: str | None = Field(
        None, max_length=500, description="Logo path if already uploaded; prefer multipart file"
    )
    website: str | None = Field(None, max_length=255)
    is_active: bool = Field(True, description="Status: Active=true / Inactive=false")
    contact_person: str | None = Field(None, max_length=200)
    email: str | None = Field(None, max_length=255)
    phone: str | None = Field(None, max_length=30)
    address: str | None = Field(None, max_length=500)


class BrandUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=200)
    description: str | None = Field(None, max_length=255)
    logo: str | None = Field(None, max_length=500)
    website: str | None = Field(None, max_length=255)
    is_active: bool | None = None
    contact_person: str | None = Field(None, max_length=200)
    email: str | None = Field(None, max_length=255)
    phone: str | None = Field(None, max_length=30)
    address: str | None = Field(None, max_length=500)


class BrandResponse(BaseModel):
    id: str
    company_id: str
    code: str
    name: str
    description: str | None
    logo: str | None
    website: str | None
    is_active: bool
    contact_person: str | None
    email: str | None
    phone: str | None
    address: str | None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class UnitTypeCreate(BaseModel):
    code: str = Field(..., min_length=1, max_length=30, description="Unique unit code")
    name: str = Field(..., min_length=1, max_length=100, description="Unit name")
    base_unit_id: str | None = Field(None, description="Base unit ID from /base-units")
    unit_kind: UnitKind = Field(UnitKind.INDIVIDUAL, description="Unit type classification")
    conversion_rate: Decimal = Field(
        default=Decimal("1.0000"),
        gt=0,
        description="How many base units equal 1 of this unit",
    )
    decimal_places: int = Field(2, ge=0, le=6, description="Allowed decimal places")
    is_active: bool = Field(True, description="Status: Active=true / Inactive=false")
    sort_order: int | None = Field(None, ge=0, description="Lower numbers appear first")
    description: str | None = Field(None, max_length=255)
    remarks: str | None = Field(None, max_length=255)


class UnitTypeUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=100)
    base_unit_id: str | None = None
    unit_kind: UnitKind | None = None
    conversion_rate: Decimal | None = Field(None, gt=0)
    decimal_places: int | None = Field(None, ge=0, le=6)
    is_active: bool | None = None
    sort_order: int | None = Field(None, ge=0)
    description: str | None = Field(None, max_length=255)
    remarks: str | None = Field(None, max_length=255)


class UnitTypeResponse(BaseModel):
    id: str
    company_id: str
    code: str
    name: str
    base_unit_id: str | None
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    unit_kind: UnitKind
    conversion_rate: Decimal
    decimal_places: int
    is_active: bool
    sort_order: int | None
    description: str | None
    remarks: str | None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class ItemCreate(BaseModel):
    sku: str | None = Field(
        None,
        min_length=1,
        max_length=50,
        description="Item code; auto-generated (e.g. ITM-0001) if omitted",
    )
    name: str = Field(..., min_length=1, max_length=200)
    barcode: str | None = Field(None, max_length=100)
    image: str | None = Field(
        None, max_length=500, description="Image path if already uploaded; prefer multipart file"
    )
    category_id: str = Field(..., min_length=1)
    item_type_id: str = Field(..., min_length=1)
    group_id: str = Field(..., min_length=1)
    brand_name: str | None = Field(None, max_length=100)
    base_unit_id: str = Field(..., min_length=1, description="Base unit ID")
    warehouse_id: str = Field(..., min_length=1)
    opening_stock_qty: Decimal = Field(default=Decimal("0.0000"), ge=0)
    reorder_level: Decimal = Field(default=Decimal("0.0000"), ge=0)
    sale_price: Decimal = Field(..., ge=0, description="Selling price")
    purchase_price: Decimal = Field(default=Decimal("0.0000"), ge=0, description="Cost price")
    tax_percent: Decimal = Field(default=Decimal("0.0000"), ge=0, le=100)
    description: str | None = Field(None, max_length=500)
    specifications: str | None = Field(None, max_length=500)
    remarks: str | None = Field(None, max_length=500)
    unit_type_id: str | None = None
    pricing_model: PricingModel = PricingModel.AVERAGE_COST
    track_inventory: bool = True
    inventory_account_id: str | None = None
    expense_account_id: str | None = None
    cogs_account_id: str | None = None
    is_active: bool = True


class ItemUpdate(BaseModel):
    sku: str | None = Field(None, min_length=1, max_length=50)
    name: str | None = Field(None, min_length=1, max_length=200)
    barcode: str | None = Field(None, max_length=100)
    image: str | None = Field(None, max_length=500)
    category_id: str | None = Field(None, min_length=1)
    item_type_id: str | None = Field(None, min_length=1)
    group_id: str | None = Field(None, min_length=1)
    brand_name: str | None = Field(None, max_length=100)
    base_unit_id: str | None = Field(None, min_length=1)
    warehouse_id: str | None = Field(None, min_length=1)
    reorder_level: Decimal | None = Field(None, ge=0)
    sale_price: Decimal | None = Field(None, ge=0)
    purchase_price: Decimal | None = Field(None, ge=0)
    tax_percent: Decimal | None = Field(None, ge=0, le=100)
    description: str | None = Field(None, max_length=500)
    specifications: str | None = Field(None, max_length=500)
    remarks: str | None = Field(None, max_length=500)
    unit_type_id: str | None = None
    pricing_model: PricingModel | None = None
    track_inventory: bool | None = None
    inventory_account_id: str | None = None
    expense_account_id: str | None = None
    cogs_account_id: str | None = None
    is_active: bool | None = None


class ItemResponse(BaseModel):
    id: str
    company_id: str
    sku: str
    name: str
    barcode: str | None
    image: str | None = None
    description: str | None
    specifications: str | None
    remarks: str | None
    category_id: str
    category_code: str | None = None
    category_name: str | None = None
    item_type_id: str
    item_type_code: str | None = None
    item_type_name: str | None = None
    group_id: str
    group_code: str | None = None
    group_name: str | None = None
    brand_name: str | None
    base_unit_id: str
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    warehouse_id: str
    warehouse_code: str | None = None
    warehouse_name: str | None = None
    unit_type_id: str | None
    pricing_model: PricingModel
    purchase_price: Decimal
    sale_price: Decimal
    tax_percent: Decimal
    reorder_level: Decimal
    track_inventory: bool
    inventory_account_id: str | None
    expense_account_id: str | None
    cogs_account_id: str | None
    is_active: bool
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class InventoryBalanceResponse(BaseModel):
    id: str | None = None
    company_id: str
    item_id: str
    warehouse_id: str | None = None
    quantity_on_hand: Decimal
    quantity_reserved: Decimal
    average_cost: Decimal
    last_cost: Decimal
    updated_at: datetime | None = None

    model_config = {"from_attributes": True}


class InventoryTransactionCreate(BaseModel):
    item_id: str
    warehouse_id: str | None = None
    txn_type: InventoryTxnType
    txn_date: date
    quantity_in: Decimal = Field(default=Decimal("0.0000"), ge=0)
    quantity_out: Decimal = Field(default=Decimal("0.0000"), ge=0)
    unit_cost: Decimal = Field(default=Decimal("0.0000"), ge=0)
    reference_type: str | None = None
    reference_id: str | None = None
    reference_number: str | None = None
    notes: str | None = None


class InventoryTransactionResponse(BaseModel):
    id: str
    company_id: str
    item_id: str
    warehouse_id: str | None = None
    txn_type: InventoryTxnType
    txn_date: date
    quantity_in: Decimal
    quantity_out: Decimal
    unit_cost: Decimal
    total_cost: Decimal
    balance_after: Decimal
    reference_type: str | None
    reference_id: str | None
    reference_number: str | None
    notes: str | None
    created_at: datetime

    model_config = {"from_attributes": True}


class ItemTransactionLineCreate(BaseModel):
    item_id: str
    description: str | None = None
    batch_lot_no: str | None = Field(None, max_length=100)
    expiry_date: date | None = None
    base_unit_id: str | None = None
    quantity: Decimal = Field(..., gt=0)
    unit_cost: Decimal = Field(default=Decimal("0.0000"), ge=0)
    discount_type: AmountType = AmountType.PERCENT
    discount_value: Decimal = Field(default=Decimal("0.0000"), ge=0)
    tax_type: AmountType = AmountType.PERCENT
    tax_rate: Decimal = Field(default=Decimal("0.0000"), ge=0, description="Tax % or fixed amount")


class ItemTransactionCreate(BaseModel):
    txn_type: InventoryTxnType
    txn_date: datetime
    reference_type: ItemTransactionReferenceType | None = None
    reference_number: str | None = Field(None, max_length=100)
    direction: InventoryTxnDirection
    warehouse_id: str
    vendor_id: str | None = None
    po_date: date | None = None
    expected_date: date | None = None
    grn_number: str | None = Field(None, max_length=50)
    remarks: str | None = None
    internal_note: str | None = None
    tags: list[str] = Field(default_factory=list)
    attachments: list[str] = Field(default_factory=list)
    transport_charges: Decimal = Field(default=Decimal("0.00"), ge=0)
    rounding: Decimal = Field(default=Decimal("0.00"))
    lines: list[ItemTransactionLineCreate] = Field(..., min_length=1)
    post_now: bool = Field(
        default=False,
        description="If true, post immediately (Save Transaction); else save as draft",
    )


class ItemTransactionUpdate(BaseModel):
    txn_type: InventoryTxnType | None = None
    txn_date: datetime | None = None
    reference_type: ItemTransactionReferenceType | None = None
    reference_number: str | None = Field(None, max_length=100)
    direction: InventoryTxnDirection | None = None
    warehouse_id: str | None = None
    vendor_id: str | None = None
    po_date: date | None = None
    expected_date: date | None = None
    grn_number: str | None = Field(None, max_length=50)
    remarks: str | None = None
    internal_note: str | None = None
    tags: list[str] | None = None
    attachments: list[str] | None = None
    transport_charges: Decimal | None = Field(None, ge=0)
    rounding: Decimal | None = None
    lines: list[ItemTransactionLineCreate] | None = None


class ItemTransactionLineResponse(BaseModel):
    id: str | None = None
    item_transaction_id: str | None = None
    line_number: int
    item_id: str
    item_sku: str | None = None
    item_name: str | None = None
    description: str | None = None
    batch_lot_no: str | None = None
    expiry_date: date | None = None
    base_unit_id: str | None = None
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    quantity: Decimal
    unit_cost: Decimal
    discount_type: AmountType
    discount_value: Decimal
    discount_amount: Decimal
    tax_type: AmountType
    tax_rate: Decimal
    tax_amount: Decimal
    line_total: Decimal

    model_config = {"from_attributes": True}


class ItemTransactionResponse(BaseModel):
    id: str
    company_id: str
    txn_number: str
    txn_type: InventoryTxnType
    txn_date: datetime
    reference_type: ItemTransactionReferenceType | None = None
    reference_number: str | None = None
    direction: InventoryTxnDirection
    warehouse_id: str
    warehouse_code: str | None = None
    warehouse_name: str | None = None
    vendor_id: str | None = None
    vendor_code: str | None = None
    vendor_name: str | None = None
    po_date: date | None = None
    expected_date: date | None = None
    grn_number: str | None = None
    remarks: str | None = None
    internal_note: str | None = None
    tags: list[str] = Field(default_factory=list)
    attachments: list[str] = Field(default_factory=list)
    status: ItemTransactionStatus
    total_quantity: Decimal
    subtotal: Decimal
    discount_amount: Decimal
    tax_amount: Decimal
    transport_charges: Decimal
    rounding: Decimal
    grand_total: Decimal
    created_by: str | None = None
    created_by_name: str | None = None
    posted_at: datetime | None = None
    cancelled_at: datetime | None = None
    lines: list[ItemTransactionLineResponse] = Field(default_factory=list)
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class StockTransferLineCreate(BaseModel):
    item_id: str = Field(..., min_length=1)
    transfer_qty: Decimal = Field(..., gt=0)
    base_unit_id: str | None = None
    batch_lot_no: str | None = Field(None, max_length=100)
    unit_cost: Decimal | None = Field(None, ge=0, description="Defaults to item average/purchase cost")


class StockTransferCreate(BaseModel):
    transfer_date: date
    expected_delivery_date: date
    priority: StockTransferPriority = StockTransferPriority.NORMAL
    reason: StockTransferReason
    reference: str | None = Field(None, max_length=100)
    notes: str | None = Field(None, max_length=500)
    from_warehouse_id: str = Field(..., min_length=1)
    to_warehouse_id: str = Field(..., min_length=1)
    lines: list[StockTransferLineCreate] = Field(..., min_length=1)
    submit_for_review: bool = Field(
        default=False,
        description="False = Save as Draft; True = Next: Review",
    )


class StockTransferUpdate(BaseModel):
    transfer_date: date | None = None
    expected_delivery_date: date | None = None
    priority: StockTransferPriority | None = None
    reason: StockTransferReason | None = None
    reference: str | None = Field(None, max_length=100)
    notes: str | None = Field(None, max_length=500)
    from_warehouse_id: str | None = None
    to_warehouse_id: str | None = None
    lines: list[StockTransferLineCreate] | None = None


class StockTransferLineResponse(BaseModel):
    id: str
    stock_transfer_id: str | None = None
    line_number: int
    item_id: str
    item_sku: str | None = None
    item_name: str | None = None
    available_qty: Decimal
    transfer_qty: Decimal
    base_unit_id: str | None = None
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    batch_lot_no: str | None = None
    unit_cost: Decimal
    line_value: Decimal

    model_config = {"from_attributes": True}


class StockTransferResponse(BaseModel):
    id: str
    company_id: str
    transfer_number: str
    transfer_date: date
    expected_delivery_date: date
    priority: StockTransferPriority
    reason: StockTransferReason
    reference: str | None = None
    notes: str | None = None
    from_warehouse_id: str
    from_warehouse_code: str | None = None
    from_warehouse_name: str | None = None
    from_warehouse_address: str | None = None
    to_warehouse_id: str
    to_warehouse_code: str | None = None
    to_warehouse_name: str | None = None
    to_warehouse_address: str | None = None
    status: StockTransferStatus
    total_items: int
    total_quantity: Decimal
    total_transfer_value: Decimal
    created_by: str | None = None
    created_by_name: str | None = None
    submitted_at: datetime | None = None
    approved_at: datetime | None = None
    picked_at: datetime | None = None
    shipped_at: datetime | None = None
    received_at: datetime | None = None
    completed_at: datetime | None = None
    cancelled_at: datetime | None = None
    lines: list[StockTransferLineResponse] = Field(default_factory=list)
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class LocationCreate(BaseModel):
    code: str = Field(..., min_length=1, max_length=30)
    name: str = Field(..., min_length=1, max_length=200)
    address: str | None = Field(None, max_length=255)
    is_active: bool = True


class LocationUpdate(BaseModel):
    code: str | None = Field(None, min_length=1, max_length=30)
    name: str | None = Field(None, min_length=1, max_length=200)
    address: str | None = Field(None, max_length=255)
    is_active: bool | None = None


class LocationResponse(BaseModel):
    id: str
    company_id: str
    code: str
    name: str
    address: str | None = None
    is_active: bool
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class DepartmentCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=200, description="Department name")
    code: str = Field(
        ...,
        min_length=1,
        max_length=6,
        description="Short unique code, max 6 characters",
    )
    head_id: str | None = Field(None, description="Required when status=active")
    location_id: str | None = Field(None, description="Required when status=active")
    parent_department_id: str | None = Field(
        None, description="None = top-level department"
    )
    monthly_issue_budget: Decimal | None = Field(
        None, ge=0, description="Max items issuable per month"
    )
    description: str | None = None
    status: DepartmentStatus = Field(
        DepartmentStatus.ACTIVE,
        description="draft = Save as Draft; active/inactive = Save Department",
    )
    is_active: bool | None = Field(
        None, description="Deprecated — derived from status (active=true)"
    )
    notify_email: str | None = Field(None, max_length=255)
    low_stock_alert: LowStockAlertTarget = LowStockAlertTarget.HEAD


class DepartmentUpdate(BaseModel):
    name: str | None = Field(None, min_length=1, max_length=200)
    code: str | None = Field(None, min_length=1, max_length=6)
    head_id: str | None = None
    location_id: str | None = None
    parent_department_id: str | None = None
    monthly_issue_budget: Decimal | None = Field(None, ge=0)
    description: str | None = None
    status: DepartmentStatus | None = None
    is_active: bool | None = None
    notify_email: str | None = Field(None, max_length=255)
    low_stock_alert: LowStockAlertTarget | None = None


class DepartmentResponse(BaseModel):
    id: str
    company_id: str
    code: str
    name: str
    head_id: str | None = None
    head_name: str | None = None
    location_id: str | None = None
    location_code: str | None = None
    location_name: str | None = None
    parent_department_id: str | None = None
    parent_department_code: str | None = None
    parent_department_name: str | None = None
    monthly_issue_budget: Decimal | None = None
    description: str | None = None
    status: DepartmentStatus
    is_active: bool
    notify_email: str | None = None
    low_stock_alert: LowStockAlertTarget
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class DepartmentIssueLineCreate(BaseModel):
    item_id: str = Field(..., min_length=1)
    issue_qty: Decimal = Field(..., gt=0)
    base_unit_id: str | None = None
    remarks: str | None = Field(None, max_length=255)
    unit_cost: Decimal | None = Field(
        None, ge=0, description="Defaults to warehouse average/purchase cost"
    )


class DepartmentIssueCreate(BaseModel):
    issue_date: date
    required_date: date
    priority: DepartmentIssuePriority = DepartmentIssuePriority.NORMAL
    department_id: str = Field(..., min_length=1)
    requested_by_id: str | None = None
    designation: str | None = Field(None, max_length=100)
    cost_center: str | None = Field(None, max_length=100)
    issue_type: DepartmentIssueType = DepartmentIssueType.REGULAR
    reason: DepartmentIssueReason
    reference: str | None = Field(None, max_length=100)
    notes: str | None = Field(None, max_length=300)
    from_warehouse_id: str = Field(..., min_length=1)
    lines: list[DepartmentIssueLineCreate] = Field(..., min_length=1)
    attachments: list[str] = Field(default_factory=list)
    submit_for_approval: bool = Field(
        default=False,
        description="False = Save as Draft; True = Submit for Approval (Review)",
    )


class DepartmentIssueUpdate(BaseModel):
    issue_date: date | None = None
    required_date: date | None = None
    priority: DepartmentIssuePriority | None = None
    department_id: str | None = None
    requested_by_id: str | None = None
    designation: str | None = Field(None, max_length=100)
    cost_center: str | None = Field(None, max_length=100)
    issue_type: DepartmentIssueType | None = None
    reason: DepartmentIssueReason | None = None
    reference: str | None = Field(None, max_length=100)
    notes: str | None = Field(None, max_length=300)
    from_warehouse_id: str | None = None
    lines: list[DepartmentIssueLineCreate] | None = None
    attachments: list[str] | None = None


class DepartmentIssueLineResponse(BaseModel):
    id: str
    department_issue_id: str | None = None
    line_number: int
    item_id: str
    item_sku: str | None = None
    item_name: str | None = None
    available_qty: Decimal
    issue_qty: Decimal
    base_unit_id: str | None = None
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    remarks: str | None = None
    unit_cost: Decimal
    line_value: Decimal

    model_config = {"from_attributes": True}


class DepartmentIssueResponse(BaseModel):
    id: str
    company_id: str
    issue_number: str
    issue_date: date
    required_date: date
    priority: DepartmentIssuePriority
    department_id: str
    department_code: str | None = None
    department_name: str | None = None
    requested_by_id: str | None = None
    requested_by_name: str | None = None
    designation: str | None = None
    cost_center: str | None = None
    issue_type: DepartmentIssueType
    reason: DepartmentIssueReason
    reference: str | None = None
    notes: str | None = None
    from_warehouse_id: str
    from_warehouse_code: str | None = None
    from_warehouse_name: str | None = None
    status: DepartmentIssueStatus
    total_items: int
    total_quantity: Decimal
    total_estimated_value: Decimal
    attachments: list[str] = Field(default_factory=list)
    created_by: str | None = None
    created_by_name: str | None = None
    submitted_at: datetime | None = None
    approved_at: datetime | None = None
    issued_at: datetime | None = None
    completed_at: datetime | None = None
    cancelled_at: datetime | None = None
    lines: list[DepartmentIssueLineResponse] = Field(default_factory=list)
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class DashboardKpiMetricResponse(BaseModel):
    current: Decimal
    previous: Decimal
    change_percent: Decimal | None = None

    model_config = {"from_attributes": True}


class DashboardTrendPointResponse(BaseModel):
    date: date
    issues_count: int
    total_quantity: Decimal
    total_value: Decimal

    model_config = {"from_attributes": True}


class DashboardBreakdownSliceResponse(BaseModel):
    id: str | None = None
    code: str | None = None
    name: str
    issues_count: int
    total_quantity: Decimal
    total_value: Decimal
    percent_of_total: Decimal

    model_config = {"from_attributes": True}


class DepartmentIssueSummaryResponse(BaseModel):
    id: str
    issue_number: str
    issue_date: date
    required_date: date | None = None
    status: DepartmentIssueStatus
    priority: DepartmentIssuePriority
    department_id: str
    department_code: str | None = None
    department_name: str | None = None
    from_warehouse_id: str
    from_warehouse_code: str | None = None
    from_warehouse_name: str | None = None
    requested_by_id: str | None = None
    requested_by_name: str | None = None
    total_items: int
    total_quantity: Decimal
    total_estimated_value: Decimal
    submitted_at: datetime | None = None

    model_config = {"from_attributes": True}


class QuickReportLinkResponse(BaseModel):
    key: str
    title: str
    description: str
    path: str

    model_config = {"from_attributes": True}


class DepartmentIssueDashboardResponse(BaseModel):
    from_date: date
    to_date: date
    previous_from_date: date
    previous_to_date: date
    total_issues: DashboardKpiMetricResponse
    items_issued: DashboardKpiMetricResponse
    total_departments: DashboardKpiMetricResponse
    total_warehouses: DashboardKpiMetricResponse
    total_value_issued: DashboardKpiMetricResponse
    pending_approvals: DashboardKpiMetricResponse
    trend: list[DashboardTrendPointResponse] = Field(default_factory=list)
    by_department: list[DashboardBreakdownSliceResponse] = Field(default_factory=list)
    by_warehouse: list[DashboardBreakdownSliceResponse] = Field(default_factory=list)
    recent_issues: list[DepartmentIssueSummaryResponse] = Field(default_factory=list)
    pending_approvals_list: list[DepartmentIssueSummaryResponse] = Field(
        default_factory=list
    )
    quick_reports: list[QuickReportLinkResponse] = Field(default_factory=list)

    model_config = {"from_attributes": True}


class StockReportRowResponse(BaseModel):
    item_id: str
    item_sku: str
    item_name: str
    category_id: str | None = None
    category_code: str | None = None
    category_name: str | None = None
    item_type_id: str | None = None
    item_type_code: str | None = None
    item_type_name: str | None = None
    warehouse_id: str
    warehouse_code: str | None = None
    warehouse_name: str | None = None
    opening_qty: Decimal
    quantity_on_hand: Decimal
    quantity_reserved: Decimal
    available_qty: Decimal
    base_unit_id: str | None = None
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    unit_cost: Decimal
    stock_value: Decimal
    reorder_level: Decimal
    stock_status: StockReportStatus
    is_active: bool = True

    model_config = {"from_attributes": True}


class StockStatusSliceResponse(BaseModel):
    status: StockReportStatus
    count: int
    percent_of_total: Decimal


class StockTopItemResponse(BaseModel):
    item_id: str
    item_sku: str
    item_name: str
    warehouse_id: str
    warehouse_name: str | None = None
    quantity_on_hand: Decimal
    unit_cost: Decimal
    stock_value: Decimal


class StockReportResponse(BaseModel):
    from_date: date | None = None
    to_date: date | None = None
    report_basis: StockReportBasis = StockReportBasis.CURRENT_STOCK
    total_items: int
    total_quantity: Decimal
    total_stock_value: Decimal
    total_warehouses: int
    low_stock_items: int
    by_warehouse_value: list[DashboardBreakdownSliceResponse] = Field(default_factory=list)
    status_overview: list[StockStatusSliceResponse] = Field(default_factory=list)
    top_items_by_value: list[StockTopItemResponse] = Field(default_factory=list)
    rows: list[StockReportRowResponse] = Field(default_factory=list)
    rows_total: int
    page: int
    page_size: int
    total_pages: int

    model_config = {"from_attributes": True}
