from datetime import date, datetime
from decimal import Decimal

from pydantic import BaseModel, Field

from app.domain.enums import (
    CustomerBusinessType,
    PaymentTerms,
    PreferredPaymentMethod,
    SalesDeliveryStatus,
    SalesInvoiceStatus,
    SalesOrderStatus,
    SalesPaymentStatus,
)


class Customer(BaseModel):
    id: str | None = None
    company_id: str
    code: str
    name: str
    business_type: CustomerBusinessType | None = None
    contact_person: str
    designation: str | None = None
    phone: str
    alternate_phone: str | None = None
    email: str | None = None
    website: str | None = None
    ntn: str | None = None
    sales_tax_no: str | None = None
    address_line1: str
    address_line2: str | None = None
    city: str
    state_province: str | None = None
    country: str = "Pakistan"
    postal_code: str | None = None
    notes: str | None = None
    payment_terms: PaymentTerms | None = None
    payment_terms_days: int = 30
    credit_limit: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    opening_balance: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    currency: str = "PKR"
    so_prefix: str | None = None
    default_warehouse_id: str | None = None
    default_warehouse_code: str | None = None
    default_warehouse_name: str | None = None
    preferred_payment_method: PreferredPaymentMethod | None = None
    logo: str | None = None
    address: str | None = None
    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 SalesOrderLine(BaseModel):
    id: str | None = None
    sales_order_id: str | None = None
    line_number: int
    item_id: str
    item_sku: str | None = None
    item_name: str | None = None
    description: str | None = None
    quantity: Decimal = Field(..., decimal_places=4)
    reserved_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    picked_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    shipped_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    invoiced_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    available_quantity: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    is_available: bool = False
    unit_price: Decimal = Field(..., decimal_places=4)
    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(..., decimal_places=2)

    model_config = {"from_attributes": True}


class SalesOrder(BaseModel):
    id: str | None = None
    company_id: str
    so_number: str
    customer_id: str
    customer_code: str | None = None
    customer_name: str | None = None
    customer_email: str | None = None
    customer_phone: str | None = None
    warehouse_id: str | None = None
    warehouse_code: str | None = None
    warehouse_name: str | None = None
    order_date: date
    delivery_date: date | None = None
    delivery_address: str | None = None
    delivery_contact: str | None = None
    delivery_phone: str | None = None
    payment_terms: PaymentTerms | None = None
    currency: str = "PKR"
    notes: str | None = None
    status: SalesOrderStatus = SalesOrderStatus.DRAFT
    subtotal: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    tax_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    total_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    created_by: str | None = None
    confirmed_at: datetime | None = None
    cancelled_at: datetime | None = None
    lines: list[SalesOrderLine] = 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 SalesDeliveryLine(BaseModel):
    id: str | None = None
    sales_delivery_id: str | None = None
    sales_order_line_id: str
    line_number: int
    item_id: str
    quantity: Decimal = Field(..., decimal_places=4)
    notes: str | None = None

    model_config = {"from_attributes": True}


class SalesDelivery(BaseModel):
    id: str | None = None
    company_id: str
    delivery_number: str
    sales_order_id: str
    customer_id: str
    delivery_date: date
    status: SalesDeliveryStatus = SalesDeliveryStatus.DRAFT
    notes: str | None = None
    confirmed_at: datetime | None = None
    lines: list[SalesDeliveryLine] = 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 SalesInvoiceLine(BaseModel):
    id: str | None = None
    sales_invoice_id: str | None = None
    line_number: int
    item_id: str | None = None
    account_id: str | None = None
    description: str | None = None
    quantity: Decimal = Field(default=Decimal("1.0000"), decimal_places=4)
    unit_price: Decimal = Field(..., decimal_places=4)
    tax_rate: Decimal = Field(default=Decimal("0.0000"), decimal_places=4)
    line_total: Decimal = Field(..., decimal_places=2)
    sales_order_line_id: str | None = None
    sales_delivery_line_id: str | None = None

    model_config = {"from_attributes": True}


class SalesInvoice(BaseModel):
    id: str | None = None
    company_id: str
    invoice_number: str
    customer_id: str
    sales_order_id: str | None = None
    delivery_id: str | None = None
    invoice_date: date
    due_date: date | None = None
    status: SalesInvoiceStatus = SalesInvoiceStatus.DRAFT
    ar_account_id: str | None = None
    notes: str | None = None
    subtotal: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    tax_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    total_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    amount_paid: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    voucher_id: str | None = None
    posted_at: datetime | None = None
    lines: list[SalesInvoiceLine] = 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 SalesPaymentAllocation(BaseModel):
    id: str | None = None
    sales_payment_id: str | None = None
    sales_invoice_id: str
    amount: Decimal = Field(..., decimal_places=2)

    model_config = {"from_attributes": True}


class SalesPayment(BaseModel):
    id: str | None = None
    company_id: str
    payment_number: str
    customer_id: str
    payment_date: date
    status: SalesPaymentStatus = SalesPaymentStatus.DRAFT
    payment_method: str = "bank"
    bank_account_id: str | None = None
    ar_account_id: str | None = None
    reference: str | None = None
    notes: str | None = None
    total_amount: Decimal = Field(default=Decimal("0.00"), decimal_places=2)
    voucher_id: str | None = None
    posted_at: datetime | None = None
    allocations: list[SalesPaymentAllocation] = 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}
