"""
Pydantic schemas for billing: Invoice, InvoiceItem, Receipt.
"""
from typing import List, Optional, Dict, Any
from datetime import date, datetime
from pydantic import BaseModel, Field, field_validator

from app.models.billing import (
    InvoiceStatus, InvoiceType, ServiceCategory, ReceiptStatus
)


# ─── Invoice Item ───────────────────────────────────────────────────────────────

class InvoiceItemCreate(BaseModel):
    service_category: ServiceCategory
    service_code: Optional[str] = None
    description: str = Field(..., min_length=1, max_length=500)
    service_date: Optional[date] = None
    quantity: float = Field(default=1.0, gt=0)
    unit: str = Field(default="unité", max_length=30)
    unit_price_ht: float = Field(..., gt=0)
    tax_rate: float = Field(default=0.0, ge=0, le=100)
    discount_percent: float = Field(default=0.0, ge=0, le=100)
    extra_data: Optional[Dict[str, Any]] = None


class InvoiceItemResponse(BaseModel):
    id: int
    invoice_id: int
    service_category: ServiceCategory
    service_code: Optional[str]
    description: str
    service_date: Optional[date]
    quantity: float
    unit: str
    unit_price_ht: float
    tax_rate: float
    total_ht: float
    total_tax: float
    total_ttc: float
    discount_percent: float
    discount_amount: float
    is_cancelled: bool
    cancelled_reason: Optional[str]
    extra_data: Optional[Dict[str, Any]]
    created_at: datetime

    class Config:
        from_attributes = True


# ─── Receipt ────────────────────────────────────────────────────────────────────

class ReceiptCreate(BaseModel):
    payment_method: str = Field(..., min_length=2, max_length=50)
    payment_reference: Optional[str] = Field(None, max_length=200)
    amount: float = Field(..., gt=0)
    currency: str = Field(default="XOF", max_length=3)
    notes: Optional[str] = None

    @field_validator("payment_method")
    @classmethod
    def validate_payment_method(cls, v: str) -> str:
        allowed = [
            "cash", "credit_card", "debit_card", "bank_transfer",
            "check", "mobile_payment", "wave", "orange_money",
            "free_money", "voucher", "credit", "other"
        ]
        if v.lower() not in allowed:
            raise ValueError(f"Invalid payment method. Allowed: {', '.join(allowed)}")
        return v.lower()


class ReceiptResponse(BaseModel):
    id: int
    receipt_number: str
    invoice_id: int
    payment_method: str
    payment_reference: Optional[str]
    amount: float
    currency: str
    payment_date: datetime
    status: ReceiptStatus
    cancellation_reason: Optional[str]
    notes: Optional[str]
    received_by_id: Optional[int]
    created_at: datetime

    class Config:
        from_attributes = True


# ─── Invoice ────────────────────────────────────────────────────────────────────

class InvoiceCreate(BaseModel):
    establishment_id: int
    client_id: Optional[int] = None
    reservation_id: Optional[int] = None
    folio_id: Optional[int] = None
    invoice_type: InvoiceType = InvoiceType.MIXED
    issue_date: Optional[date] = None
    due_date: Optional[date] = None
    currency: str = Field(default="XOF", max_length=3)
    discount_percent: float = Field(default=0.0, ge=0, le=100)
    notes: Optional[str] = None
    payment_terms: Optional[str] = None
    items: List[InvoiceItemCreate] = Field(default_factory=list)


class InvoiceUpdate(BaseModel):
    invoice_type: Optional[InvoiceType] = None
    due_date: Optional[date] = None
    discount_percent: Optional[float] = Field(None, ge=0, le=100)
    notes: Optional[str] = None
    payment_terms: Optional[str] = None


class InvoiceResponse(BaseModel):
    id: int
    invoice_number: str
    invoice_type: InvoiceType
    status: InvoiceStatus
    establishment_id: int
    client_id: Optional[int]
    reservation_id: Optional[int]
    folio_id: Optional[int]
    issue_date: date
    due_date: Optional[date]
    subtotal_ht: float
    total_tax: float
    total_ttc: float
    total_paid: float
    balance_due: float
    currency: str
    discount_percent: float
    discount_amount: float
    client_name: Optional[str]
    client_email: Optional[str]
    client_address: Optional[str]
    client_tax_id: Optional[str]
    notes: Optional[str]
    payment_terms: Optional[str]
    original_invoice_id: Optional[int]
    created_by_id: Optional[int]
    items: List[InvoiceItemResponse] = []
    receipts: List[ReceiptResponse] = []
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class InvoiceListResponse(BaseModel):
    id: int
    invoice_number: str
    invoice_type: InvoiceType
    status: InvoiceStatus
    client_name: Optional[str]
    issue_date: date
    due_date: Optional[date]
    total_ttc: float
    total_paid: float
    balance_due: float
    currency: str
    created_at: datetime

    class Config:
        from_attributes = True


class CancelItemRequest(BaseModel):
    reason: str = Field(..., min_length=1)


class CancelReceiptRequest(BaseModel):
    reason: str = Field(..., min_length=1)


class CreateCreditNoteRequest(BaseModel):
    reason: str = Field(..., min_length=5)
    items_to_credit: Optional[List[int]] = None  # item IDs; None = full credit note


class InvoiceSummary(BaseModel):
    """Summary statistics for invoice dashboard."""
    total_invoices: int
    total_issued: int
    total_paid: int
    total_overdue: int
    total_revenue_ttc: float
    total_outstanding: float
    currency: str
