from datetime import date, datetime
from decimal import Decimal

from pydantic import BaseModel, ConfigDict, Field, computed_field


class InvoiceClientReviewInput(BaseModel):
    """Resultado de la revisión de la factura por el cliente (R-F-06)."""
    approved: bool
    notes: str | None = None


class InvoiceItemBase(BaseModel):
    concept: str = Field(..., max_length=60)
    description: str | None = Field(None, max_length=255)
    quantity: Decimal = Field(Decimal(1), ge=0, max_digits=12, decimal_places=2)
    unit_amount: Decimal = Field(Decimal(0), ge=0, max_digits=14, decimal_places=2)


class InvoiceItemCreate(InvoiceItemBase):
    invoice_id: int


class InvoiceItemUpdate(BaseModel):
    concept: str | None = Field(None, max_length=60)
    description: str | None = Field(None, max_length=255)
    quantity: Decimal | None = Field(None, ge=0, max_digits=12, decimal_places=2)
    unit_amount: Decimal | None = Field(None, ge=0, max_digits=14, decimal_places=2)


class InvoiceItemResponse(InvoiceItemBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    invoice_id: int
    tenant_id: int
    company_id: int

    @computed_field
    @property
    def line_total(self) -> Decimal:
        return (self.quantity or Decimal(0)) * (self.unit_amount or Decimal(0))


class PaymentBase(BaseModel):
    amount: Decimal = Field(..., gt=0, max_digits=14, decimal_places=2)
    payment_date: date | None = None
    method: str | None = Field(None, max_length=40)
    reference: str | None = Field(None, max_length=120)
    notes: str | None = None


class PaymentCreate(PaymentBase):
    invoice_id: int


class PaymentResponse(PaymentBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    invoice_id: int
    tenant_id: int
    company_id: int
    created_at: datetime


class InvoiceBase(BaseModel):
    reference: str | None = Field(None, max_length=40)
    shipment_id: int | None = None
    quote_id: int | None = None
    account_id: int | None = None
    currency: str = Field("MXN", max_length=3)
    issue_date: date | None = None
    due_date: date | None = None
    tax_rate: Decimal = Field(Decimal(0), ge=0, le=100, max_digits=5, decimal_places=2)
    bank_info: str | None = None
    notes: str | None = None
    owner_user_id: str | None = Field(None, max_length=64)


class InvoiceCreate(InvoiceBase):
    pass


class InvoiceUpdate(BaseModel):
    reference: str | None = Field(None, max_length=40)
    shipment_id: int | None = None
    quote_id: int | None = None
    account_id: int | None = None
    currency: str | None = Field(None, max_length=3)
    issue_date: date | None = None
    due_date: date | None = None
    tax_rate: Decimal | None = Field(None, ge=0, le=100, max_digits=5, decimal_places=2)
    bank_info: str | None = None
    notes: str | None = None
    owner_user_id: str | None = Field(None, max_length=64)


class InvoiceResponse(InvoiceBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    status: str
    subtotal: Decimal
    tax_amount: Decimal
    total: Decimal
    paid_amount: Decimal
    balance: Decimal
    ops_cost_total: Decimal | None = None
    sent_at: datetime | None = None
    paid_at: datetime | None = None
    pdf_file_key: str | None = None
    client_reviewed_at: datetime | None = None
    client_approved: bool | None = None
    review_notes: str | None = None
    created_by: str | None = None
    updated_by: str | None = None
    tenant_id: int
    company_id: int
    created_at: datetime
    updated_at: datetime
