# app/modules/orders/schemas/invoice.py
"""
Pydantic schemas for invoice operations.

Supports invoice settings management and invoice generation.
"""

from datetime import datetime
from decimal import Decimal

from pydantic import BaseModel, ConfigDict, Field

# ============================================================================
# Invoice Settings Schemas
# ============================================================================


class StoreInvoiceSettingsCreate(BaseModel):
    """Schema for creating store invoice settings."""

    merchant_name: str = Field(..., min_length=1, max_length=255)
    merchant_address: str | None = Field(None, max_length=255)
    merchant_city: str | None = Field(None, max_length=100)
    merchant_postal_code: str | None = Field(None, max_length=20)
    merchant_country: str = Field(default="LU", min_length=2, max_length=2)

    vat_number: str | None = Field(None, max_length=50)
    is_vat_registered: bool = True

    is_oss_registered: bool = False
    oss_registration_country: str | None = Field(None, min_length=2, max_length=2)

    invoice_prefix: str = Field(default="INV", max_length=20)
    invoice_number_padding: int = Field(default=5, ge=1, le=10)

    payment_terms: str | None = None
    bank_name: str | None = Field(None, max_length=255)
    bank_iban: str | None = Field(None, max_length=50)
    bank_bic: str | None = Field(None, max_length=20)

    footer_text: str | None = None
    default_vat_rate: Decimal = Field(default=Decimal("17.00"), ge=0, le=100)


class StoreInvoiceSettingsUpdate(BaseModel):
    """Schema for updating store invoice settings."""

    merchant_name: str | None = Field(None, min_length=1, max_length=255)
    merchant_address: str | None = Field(None, max_length=255)
    merchant_city: str | None = Field(None, max_length=100)
    merchant_postal_code: str | None = Field(None, max_length=20)
    merchant_country: str | None = Field(None, min_length=2, max_length=2)

    vat_number: str | None = None
    is_vat_registered: bool | None = None

    is_oss_registered: bool | None = None
    oss_registration_country: str | None = None

    invoice_prefix: str | None = Field(None, max_length=20)
    invoice_number_padding: int | None = Field(None, ge=1, le=10)

    payment_terms: str | None = None
    bank_name: str | None = Field(None, max_length=255)
    bank_iban: str | None = Field(None, max_length=50)
    bank_bic: str | None = Field(None, max_length=20)

    footer_text: str | None = None
    default_vat_rate: Decimal | None = Field(None, ge=0, le=100)


class StoreInvoiceSettingsResponse(BaseModel):
    """Schema for store invoice settings response."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int

    merchant_name: str
    merchant_address: str | None
    merchant_city: str | None
    merchant_postal_code: str | None
    merchant_country: str

    vat_number: str | None
    is_vat_registered: bool

    is_oss_registered: bool
    oss_registration_country: str | None

    invoice_prefix: str
    invoice_next_number: int
    invoice_number_padding: int

    payment_terms: str | None
    bank_name: str | None
    bank_iban: str | None
    bank_bic: str | None

    footer_text: str | None
    default_vat_rate: Decimal

    created_at: datetime
    updated_at: datetime


# ============================================================================
# Invoice Line Item Schemas
# ============================================================================


class InvoiceLineItem(BaseModel):
    """Schema for invoice line item."""

    description: str
    quantity: int = Field(..., ge=1)
    unit_price_cents: int
    total_cents: int
    sku: str | None = None
    ean: str | None = None


class InvoiceLineItemResponse(BaseModel):
    """Schema for invoice line item in response."""

    description: str
    quantity: int
    unit_price_cents: int
    total_cents: int
    sku: str | None = None
    ean: str | None = None

    @property
    def unit_price(self) -> float:
        return self.unit_price_cents / 100

    @property
    def total(self) -> float:
        return self.total_cents / 100


# ============================================================================
# Invoice Address Schemas
# ============================================================================


class InvoiceSellerDetails(BaseModel):
    """Seller details for invoice."""

    merchant_name: str
    address: str | None = None
    city: str | None = None
    postal_code: str | None = None
    country: str
    vat_number: str | None = None


class InvoiceBuyerDetails(BaseModel):
    """Buyer details for invoice."""

    name: str
    email: str | None = None
    address: str | None = None
    city: str | None = None
    postal_code: str | None = None
    country: str
    vat_number: str | None = None  # For B2B


# ============================================================================
# Invoice Schemas
# ============================================================================


class InvoiceCreate(BaseModel):
    """Schema for creating an invoice from an order."""

    order_id: int
    notes: str | None = None


class InvoiceManualCreate(BaseModel):
    """Schema for creating a manual invoice (without order)."""

    buyer_details: InvoiceBuyerDetails
    line_items: list[InvoiceLineItem]
    notes: str | None = None
    payment_terms: str | None = None


class InvoiceResponse(BaseModel):
    """Schema for invoice response."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int
    order_id: int | None

    invoice_number: str
    invoice_date: datetime
    status: str

    seller_details: dict
    buyer_details: dict
    line_items: list[dict]

    vat_regime: str
    destination_country: str | None
    vat_rate: Decimal
    vat_rate_label: str | None

    currency: str
    subtotal_cents: int
    vat_amount_cents: int
    total_cents: int

    payment_terms: str | None
    bank_details: dict | None
    footer_text: str | None

    pdf_generated_at: datetime | None
    pdf_path: str | None

    notes: str | None

    created_at: datetime
    updated_at: datetime

    @property
    def subtotal(self) -> float:
        return self.subtotal_cents / 100

    @property
    def vat_amount(self) -> float:
        return self.vat_amount_cents / 100

    @property
    def total(self) -> float:
        return self.total_cents / 100


class InvoiceListResponse(BaseModel):
    """Schema for invoice list response (summary)."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    invoice_number: str
    invoice_date: datetime
    status: str
    currency: str
    total_cents: int
    order_id: int | None

    # Buyer name for display
    buyer_name: str | None = None

    @property
    def total(self) -> float:
        return self.total_cents / 100


class InvoiceStatusUpdate(BaseModel):
    """Schema for updating invoice status."""

    status: str = Field(..., pattern="^(draft|issued|paid|cancelled)$")


# ============================================================================
# Paginated Response
# ============================================================================


class InvoiceListPaginatedResponse(BaseModel):
    """Paginated invoice list response."""

    items: list[InvoiceListResponse]
    total: int
    page: int
    per_page: int
    pages: int


# ============================================================================
# PDF Response
# ============================================================================


class InvoicePDFGeneratedResponse(BaseModel):
    """Response for PDF generation."""

    pdf_path: str
    message: str = "PDF generated successfully"


class InvoiceStatsResponse(BaseModel):
    """Invoice statistics response."""

    total_invoices: int
    total_revenue_cents: int
    draft_count: int
    issued_count: int
    paid_count: int
    cancelled_count: int

    @property
    def total_revenue(self) -> float:
        return self.total_revenue_cents / 100
