from __future__ import annotations

from datetime import datetime
from typing import Any, Optional

from pydantic import BaseModel, Field


class ProjectCreate(BaseModel):
    name: str = Field(min_length=1, max_length=255)


class ProjectUpdate(BaseModel):
    name: Optional[str] = None
    current_variant: Optional[str] = None
    decimal_number: Optional[str] = None
    board_name: Optional[str] = None


class ProjectOut(BaseModel):
    id: int
    name: str
    status: str
    current_variant: str
    zip_path: Optional[str] = None
    pcb_doc_name: Optional[str] = None
    decimal_number: str
    board_name: str
    error_message: Optional[str] = None
    created_at: datetime
    updated_at: datetime
    variants: list[str] = []
    component_count: int = 0
    layer_count: int = 0

    model_config = {"from_attributes": True}


class ComponentPropertyOut(BaseModel):
    key: str
    value: str


class ComponentOut(BaseModel):
    id: int
    designator: str
    properties: list[ComponentPropertyOut] = []
    is_fitted: bool = True

    model_config = {"from_attributes": True}


class ProjectParamOut(BaseModel):
    id: int
    name: str
    value: str
    variant_name: str = ""

    model_config = {"from_attributes": True}


class DielMaterialOut(BaseModel):
    name: str
    value: str
    height: float
    diel_type: int
    layer_number: int

    model_config = {"from_attributes": True}


class PcbInfoOut(BaseModel):
    layer_count: int = 0
    materials: list[DielMaterialOut] = []


class InscriptionOut(BaseModel):
    field_number: int
    field_value: str


class InscriptionsUpdate(BaseModel):
    inscriptions: dict[int, str]


class TableRowBase(BaseModel):
    id: Optional[int] = None
    row_index: int = 0
    page_number: int = 1
    is_header: bool = False
    is_empty: bool = False
    is_auto_generated: bool = True
    stretch: bool = False
    is_underline: bool = False


class PerechenRowOut(TableRowBase):
    position: str = ""
    designation: str = ""
    quantity: str = ""
    note: str = ""


class SpecPcbRowOut(TableRowBase):
    format: str = ""
    zone: str = ""
    position: str = ""
    designation: str = ""
    name: str = ""
    quantity: str = ""
    note: str = ""


class SpecRowOut(TableRowBase):
    format: str = ""
    zone: str = ""
    position: str = ""
    designation: str = ""
    name: str = ""
    quantity: str = ""
    note: str = ""


class VedomostRowOut(TableRowBase):
    name: str = ""
    product_code: str = ""
    document_code: str = ""
    supplier: str = ""
    where_used: str = ""
    quantity_per_item: str = ""
    quantity_in_set: str = ""
    quantity_for_reg: str = ""
    total_quantity: str = ""
    note: str = ""


class SimpleListRowOut(BaseModel):
    id: Optional[int] = None
    row_index: int = 0
    designator: str = ""
    name: str = ""
    quantity: str = ""
    is_auto_generated: bool = True
    is_empty: bool = False


class TableRowsResponse(BaseModel):
    table_type: str
    rows: list[dict[str, Any]]


class TableRowsPatch(BaseModel):
    rows: list[dict[str, Any]]


class GenerateTableRequest(BaseModel):
    name_field: Optional[str] = None
    tech_reserve_percent: Optional[float] = None
    boards_count: Optional[int] = None


class LlmChatRequest(BaseModel):
    message: str = Field(min_length=1)
    table_type: str


class LlmEdit(BaseModel):
    op: str
    row_id: Optional[int] = None
    row_index: Optional[int] = None
    fields: dict[str, Any] = {}


class LlmChatResponse(BaseModel):
    reply: str
    edits: list[LlmEdit] = []
    message_id: Optional[int] = None


class LlmApplyRequest(BaseModel):
    table_type: str
    edits: list[LlmEdit]


class ExportRequest(BaseModel):
    table_type: str
    format: str = "pdf"  # pdf | xlsx


class DesignatorMappingOut(BaseModel):
    prefix: str
    singular_name: str
    plural_name: str
