from __future__ import annotations

from datetime import date
from datetime import datetime
from uuid import UUID

from pydantic import EmailStr, Field, field_validator

from app.models.customer import CustomerType
from app.models.equipment import EquipmentKind, EquipmentStatus
from app.models.user import UserRole
from app.models.validation import ValidationStatus
from app.schemas.common import EntityRead, ORMModel


class CustomerCreate(ORMModel):
    customer_type: CustomerType
    name: str
    street: str | None = None
    postal_code: str | None = None
    city: str | None = None
    phone: str | None = None
    email: EmailStr | None = None
    hygiene_officer: str | None = None
    quality_manager: str | None = None
    notes: str | None = None


class CustomerRead(CustomerCreate, EntityRead):
    pass


class CustomerUpdate(CustomerCreate):
    pass


class LocationCreate(ORMModel):
    customer_id: str
    name: str
    street: str | None = None
    postal_code: str | None = None
    city: str | None = None
    room: str | None = None


class LocationRead(LocationCreate, EntityRead):
    pass


class LocationUpdate(LocationCreate):
    pass


class ContactCreate(ORMModel):
    customer_id: str
    full_name: str
    function: str | None = None
    email: EmailStr | None = None
    phone: str | None = None


class ContactRead(ContactCreate, EntityRead):
    pass


class ContactUpdate(ContactCreate):
    pass


class DeviceCreate(ORMModel):
    customer_id: str
    location_id: str | None = None
    manufacturer: str
    model: str
    device_type: str | None = None
    serial_number: str
    year_built: int | None = None
    commissioned_on: date | None = None
    chamber_volume_liters: int | None = None
    steam_generation: str | None = None
    water_treatment: str | None = None
    documentation: str | None = None
    supplier: str | None = None


class DeviceRead(DeviceCreate, EntityRead):
    pass


class DeviceUpdate(DeviceCreate):
    pass


class EquipmentCreate(ORMModel):
    kind: EquipmentKind
    manufacturer: str | None = None
    model: str | None = None
    serial_number: str
    calibrated_on: date | None = None
    calibration_due_on: date | None = None
    certificate_document_id: str | None = None
    status: EquipmentStatus = EquipmentStatus.green


class EquipmentRead(EquipmentCreate, EntityRead):
    pass


class EquipmentUpdate(EquipmentCreate):
    pass


class ValidationCreate(ORMModel):
    report_number: str | None = None
    customer_id: UUID | None = None
    location_id: UUID | None = None
    contact_id: UUID | None = None
    device_id: UUID | None = None
    validation_type: str | None = None
    project: str | None = None
    test_location: str | None = None
    examiner_name: str | None = None
    participants: str | None = None
    operator_name: str | None = None
    scheduled_on: date | None = None
    performed_on: date | None = None
    next_validation_on: date | None = None
    revalidation_interval_months: int = 24
    next_validation_manually_overridden: bool = False
    version: int = 1
    previous_validation_id: UUID | None = None
    examiner_id: UUID | None = None
    status: ValidationStatus | str = ValidationStatus.draft
    result: str | None = None
    notes: str | None = None
    equipment_ids: list[str] = Field(default_factory=list)
    environment_conditions: dict = Field(default_factory=dict)
    documentation_checklist: list[dict] = Field(default_factory=list)
    performance_checklist: list[dict] = Field(default_factory=list)
    programs: list[dict] = Field(default_factory=list)
    loading_patterns: list[dict] = Field(default_factory=list)
    measurement_data: list[dict] = Field(default_factory=list)
    drying: dict = Field(default_factory=dict)
    recommendations: list[dict] = Field(default_factory=list)
    attachments: list[dict] = Field(default_factory=list)

    @field_validator(
        "customer_id",
        "location_id",
        "contact_id",
        "device_id",
        "examiner_id",
        "previous_validation_id",
        mode="before",
    )
    @classmethod
    def empty_string_to_none(cls, value):
        if value == "":
            return None
        return value


class ValidationRead(ValidationCreate, EntityRead):
    pass


class ValidationUpdate(ValidationCreate):
    pass


class ValidationIssue(ORMModel):
    field: str
    message: str
    section: str


class ValidationReview(ORMModel):
    status: str
    errors: list[ValidationIssue]
    warnings: list[ValidationIssue]
    complete_sections: list[str]


class ValidationImportPreviewRow(ORMModel):
    row_number: int
    data: dict
    errors: list[str]
    duplicate: bool
    resolved_customer_id: str | None = None
    resolved_location_id: str | None = None
    resolved_device_id: str | None = None


class ValidationImportPreview(ORMModel):
    rows: list[ValidationImportPreviewRow]
    valid_rows: int
    invalid_rows: int
    duplicates: int


class ValidationImportRequest(ORMModel):
    rows: list[dict]
    duplicate_strategy: str = "skip"


class ValidationImportSummary(ORMModel):
    successful: int
    skipped: int
    failed: int
    errors: list[str] = Field(default_factory=list)


class MeasurementImportValueRead(ORMModel):
    id: str
    test_run: str
    field_name: str
    raw_value: str | None = None
    normalized_value: str | None = None
    unit: str | None = None
    source_page: int | None = None
    source_text: str | None = None
    confidence: int
    confirmed: bool
    corrected_value: str | None = None


class MeasurementImportPreviewRead(ORMModel):
    id: str
    validation_id: str
    import_type: str
    original_filename: str
    sha256: str
    parser_version: str
    status: str
    values: list[MeasurementImportValueRead]


class MeasurementImportValueConfirm(ORMModel):
    id: str
    confirmed: bool = False
    corrected_value: str | None = None


class MeasurementImportConfirmRequest(ORMModel):
    values: list[MeasurementImportValueConfirm]


class UserBase(ORMModel):
    first_name: str
    last_name: str
    email: EmailStr
    role: UserRole
    is_active: bool = True
    must_change_password: bool = True


class UserCreate(UserBase):
    temporary_password: str


class UserUpdate(UserBase):
    pass


class UserRead(UserBase, EntityRead):
    last_login_at: datetime | None = None
    password_changed_at: datetime | None = None


class UserPasswordResetRequest(ORMModel):
    temporary_password: str | None = None
