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,
    StockReportStatus,
    StockTransferPriority,
    StockTransferReason,
    StockTransferStatus,
    UnitKind,
    WarehousePriority,
    WarehouseStatus,
    WarehouseType,
)


class ItemCategory(BaseModel):
    id: str | None = None
    company_id: str
    code: str
    name: str
    description: str | None = None
    is_active: bool = True
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class ItemType(BaseModel):
    id: str | None = None
    company_id: str
    category_id: str | None = None
    category_code: str | None = None
    category_name: str | None = None
    code: str
    name: str
    description: str | None = None
    is_active: bool = True
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class ItemGroup(BaseModel):
    id: str | None = None
    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 = True
    sort_order: int | None = None
    icon: str | None = None
    remarks: str | None = None
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class BaseUnit(BaseModel):
    id: str | None = None
    company_id: str
    code: str
    name: str
    description: str | None = None
    is_active: bool = True
    sort_order: int | None = None
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class UnitType(BaseModel):
    id: str | None = None
    company_id: str
    code: str
    name: str
    base_unit_id: str | None = None
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    unit_kind: UnitKind = UnitKind.INDIVIDUAL
    conversion_rate: Decimal = Field(default=Decimal("1.0000"), decimal_places=4)
    decimal_places: int = 2
    is_active: bool = True
    sort_order: int | None = None
    description: str | None = None
    remarks: str | None = None
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class Warehouse(BaseModel):
    id: str | None = None
    company_id: str
    code: str
    name: str
    warehouse_type: WarehouseType
    status: WarehouseStatus = WarehouseStatus.ACTIVE
    priority: WarehousePriority = WarehousePriority.NORMAL
    parent_warehouse_id: str | None = None
    parent_warehouse_code: str | None = None
    parent_warehouse_name: str | None = None
    manager_id: str | None = None
    manager_name: str | None = None
    contact_person: str | None = None
    phone: str | None = None
    email: str | None = 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 = True
    description: str | None = None
    capacity: str | None = None
    capacity_uom: str | None = None
    operating_hours: str | None = None
    notes: str | None = None
    remarks: str | None = 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 = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class Brand(BaseModel):
    id: str | None = None
    company_id: str
    code: str
    name: str
    description: str | None = None
    logo: str | None = None
    website: str | None = None
    is_active: bool = True
    contact_person: str | None = None
    email: str | None = None
    phone: str | None = None
    address: str | None = None
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class Item(BaseModel):
    id: str | None = None
    company_id: str
    sku: str
    name: str
    barcode: str | None = None
    image: str | None = None
    description: str | None = None
    specifications: str | None = None
    remarks: str | None = 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 = 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 = None
    pricing_model: PricingModel = PricingModel.AVERAGE_COST
    purchase_price: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    sale_price: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    tax_percent: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    reorder_level: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    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
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class InventoryBalance(BaseModel):
    id: str | None = None
    company_id: str
    item_id: str
    warehouse_id: str | None = None
    quantity_on_hand: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    quantity_reserved: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    average_cost: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    last_cost: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class InventoryTransaction(BaseModel):
    id: str | None = None
    company_id: str
    item_id: str
    warehouse_id: str | None = None
    txn_type: InventoryTxnType
    txn_date: date
    quantity_in: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    quantity_out: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    unit_cost: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    total_cost: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    balance_after: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    reference_type: str | None = None
    reference_id: str | None = None
    reference_number: str | None = None
    notes: str | None = None
    created_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class ItemTransactionLine(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 = Field(..., decimal_places=4)
    unit_cost: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    discount_type: AmountType = AmountType.PERCENT
    discount_value: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    discount_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    tax_type: AmountType = AmountType.PERCENT
    tax_rate: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    tax_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    line_total: Decimal = Field(default=Decimal("0.00"), decimal_places=2)

    model_config = {"from_attributes": True}


class ItemTransaction(BaseModel):
    id: str | None = None
    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 = ItemTransactionStatus.DRAFT
    total_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    subtotal: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    discount_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    tax_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    transport_charges: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    rounding: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    grand_total: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    created_by: str | None = None
    created_by_name: str | None = None
    posted_at: datetime | None = None
    cancelled_at: datetime | None = None
    lines: list[ItemTransactionLine] = Field(default_factory=list)
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class StockTransferLine(BaseModel):
    id: str | None = None
    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 = Field(default=Decimal("0.0000"), decimal_places=4)
    transfer_qty: Decimal = Field(..., decimal_places=4)
    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 = Field(default=Decimal("0.0000"), decimal_places=4)
    line_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)

    model_config = {"from_attributes": True}


class StockTransfer(BaseModel):
    id: str | None = None
    company_id: str
    transfer_number: str
    transfer_date: date
    expected_delivery_date: date
    priority: StockTransferPriority = StockTransferPriority.NORMAL
    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 = StockTransferStatus.DRAFT
    total_items: int = 0
    total_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    total_transfer_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    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[StockTransferLine] = Field(default_factory=list)
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class Location(BaseModel):
    id: str | None = None
    company_id: str
    code: str
    name: str
    address: str | None = None
    is_active: bool = True
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class Department(BaseModel):
    id: str | None = None
    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 = DepartmentStatus.ACTIVE
    is_active: bool = True
    notify_email: str | None = None
    low_stock_alert: LowStockAlertTarget = LowStockAlertTarget.HEAD
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class DepartmentIssueLine(BaseModel):
    id: str | None = None
    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 = Field(default=Decimal("0.0000"), decimal_places=4)
    issue_qty: Decimal = Field(..., decimal_places=4)
    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 = Field(default=Decimal("0.0000"), decimal_places=4)
    line_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)

    model_config = {"from_attributes": True}


class DepartmentIssue(BaseModel):
    id: str | None = None
    company_id: str
    issue_number: str
    issue_date: date
    required_date: date
    priority: DepartmentIssuePriority = DepartmentIssuePriority.NORMAL
    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 = DepartmentIssueType.REGULAR
    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 = DepartmentIssueStatus.DRAFT
    total_items: int = 0
    total_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    total_estimated_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    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[DepartmentIssueLine] = Field(default_factory=list)
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = {"from_attributes": True}


class DashboardKpiMetric(BaseModel):
    current: Decimal = Field(default=Decimal("0"))
    previous: Decimal = Field(default=Decimal("0"))
    change_percent: Decimal | None = None


class DashboardTrendPoint(BaseModel):
    date: date
    issues_count: int = 0
    total_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    total_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)


class DashboardBreakdownSlice(BaseModel):
    id: str | None = None
    code: str | None = None
    name: str
    issues_count: int = 0
    total_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    total_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    percent_of_total: Decimal = Field(default=Decimal("0.00"), decimal_places=2)


class DepartmentIssueSummary(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 = 0
    total_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    total_estimated_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    submitted_at: datetime | None = None


class QuickReportLink(BaseModel):
    key: str
    title: str
    description: str
    path: str


class DepartmentIssueDashboard(BaseModel):
    from_date: date
    to_date: date
    previous_from_date: date
    previous_to_date: date
    total_issues: DashboardKpiMetric
    items_issued: DashboardKpiMetric
    total_departments: DashboardKpiMetric
    total_warehouses: DashboardKpiMetric
    total_value_issued: DashboardKpiMetric
    pending_approvals: DashboardKpiMetric
    trend: list[DashboardTrendPoint] = Field(default_factory=list)
    by_department: list[DashboardBreakdownSlice] = Field(default_factory=list)
    by_warehouse: list[DashboardBreakdownSlice] = Field(default_factory=list)
    recent_issues: list[DepartmentIssueSummary] = Field(default_factory=list)
    pending_approvals_list: list[DepartmentIssueSummary] = Field(default_factory=list)
    quick_reports: list[QuickReportLink] = Field(default_factory=list)


class StockReportRow(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 = Field(default=Decimal("0.0000"), decimal_places=4)
    quantity_on_hand: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    quantity_reserved: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    available_qty: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    base_unit_id: str | None = None
    base_unit_code: str | None = None
    base_unit_name: str | None = None
    unit_cost: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    stock_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    reorder_level: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    stock_status: StockReportStatus
    is_active: bool = True


class StockStatusSlice(BaseModel):
    status: StockReportStatus
    count: int = 0
    percent_of_total: Decimal = Field(default=Decimal("0.00"), decimal_places=2)


class StockTopItem(BaseModel):
    item_id: str
    item_sku: str
    item_name: str
    warehouse_id: str
    warehouse_name: str | None = None
    quantity_on_hand: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    unit_cost: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    stock_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)


class StockReport(BaseModel):
    from_date: date | None = None
    to_date: date | None = None
    report_basis: str = "current_stock"
    total_items: int = 0
    total_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    total_stock_value: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    total_warehouses: int = 0
    low_stock_items: int = 0
    by_warehouse_value: list[DashboardBreakdownSlice] = Field(default_factory=list)
    status_overview: list[StockStatusSlice] = Field(default_factory=list)
    top_items_by_value: list[StockTopItem] = Field(default_factory=list)
    rows: list[StockReportRow] = Field(default_factory=list)
    rows_total: int = 0
    page: int = 1
    page_size: int = 20
    total_pages: int = 1
