"""
Pydantic schemas for the QA Checksheet module.
"""
from pydantic import BaseModel, Field
from typing import Optional, List, Union, Dict, Any
from uuid import UUID
from datetime import datetime, date
from decimal import Decimal


# ── Template ──────────────────────────────────────────────
class TemplateOut(BaseModel):
    template_id: UUID
    template_code: str
    template_name: str
    station_id: Optional[UUID] = None
    station_name: Optional[str] = None
    format_no: Optional[str] = None
    revision: Optional[str] = None
    revision_date: Optional[date] = None
    description: Optional[str] = None
    is_active: bool = True
    sections: Optional[List["SectionOut"]] = None

    class Config:
        from_attributes = True

class TemplateCreate(BaseModel):
    template_code: str
    template_name: str
    station_id: Optional[UUID] = None
    format_no: Optional[str] = None
    revision: Optional[str] = None
    revision_date: Optional[date] = None
    description: Optional[str] = None

class TemplateUpdate(BaseModel):
    template_name: Optional[str] = None
    station_id: Optional[UUID] = None
    format_no: Optional[str] = None
    revision: Optional[str] = None
    revision_date: Optional[date] = None
    description: Optional[str] = None
    is_active: Optional[bool] = None


# ── Section ───────────────────────────────────────────────
class SectionOut(BaseModel):
    section_id: UUID
    template_id: UUID
    section_no: int
    section_name: str
    description: Optional[str] = None
    sort_order: int = 1
    items: Optional[List["ItemOut"]] = None

    class Config:
        from_attributes = True

class SectionCreate(BaseModel):
    section_name: str
    section_no: int = 1
    description: Optional[str] = None
    sort_order: int = 1

class SectionUpdate(BaseModel):
    section_name: Optional[str] = None
    section_no: Optional[int] = None
    description: Optional[str] = None
    sort_order: Optional[int] = None


# ── Checkpoint Item ───────────────────────────────────────
class ItemOut(BaseModel):
    item_id: UUID
    section_id: UUID
    item_no: int
    area_desc: Optional[str] = None
    checkpoint_desc: str
    checkpoint_class: str = "MAJOR"
    verification_method: Optional[str] = None
    standard_specification: Optional[str] = None
    requires_measurement: bool = False
    min_value: Optional[Decimal] = None
    max_value: Optional[Decimal] = None
    unit_of_measure: Optional[str] = None
    special_feature_flag: Optional[str] = None
    frequency: Optional[str] = None
    model_specs: Optional[dict] = None
    sub_points: Optional[list] = None
    reference_diagram_url: Optional[str] = None
    sort_order: int = 1

    class Config:
        from_attributes = True

class ItemCreate(BaseModel):
    area_desc: Optional[str] = None
    checkpoint_desc: str
    checkpoint_class: str = "MAJOR"
    item_no: int = 1
    verification_method: Optional[str] = None
    standard_specification: Optional[str] = None
    requires_measurement: bool = False
    min_value: Optional[Decimal] = None
    max_value: Optional[Decimal] = None
    unit_of_measure: Optional[str] = None
    special_feature_flag: Optional[str] = None
    frequency: Optional[str] = None
    model_specs: Optional[dict] = None
    sub_points: Optional[list] = None
    reference_diagram_url: Optional[str] = None
    sort_order: int = 1

class ItemUpdate(BaseModel):
    area_desc: Optional[str] = None
    checkpoint_desc: Optional[str] = None
    checkpoint_class: Optional[str] = None
    item_no: Optional[int] = None
    verification_method: Optional[str] = None
    standard_specification: Optional[str] = None
    requires_measurement: Optional[bool] = None
    min_value: Optional[Decimal] = None
    max_value: Optional[Decimal] = None
    unit_of_measure: Optional[str] = None
    special_feature_flag: Optional[str] = None
    frequency: Optional[str] = None
    model_specs: Optional[dict] = None
    sub_points: Optional[list] = None
    reference_diagram_url: Optional[str] = None
    sort_order: Optional[int] = None


# ── Station-Template Mapping ─────────────────────────────
class StationMappingOut(BaseModel):
    map_id: UUID
    station_id: UUID
    station_name: Optional[str] = None
    template_id: UUID
    template_name: Optional[str] = None
    template_code: Optional[str] = None
    format_no: Optional[str] = None
    revision: Optional[str] = None
    model_id: Optional[UUID] = None
    model_number: Optional[str] = None
    model_ids: Optional[List[UUID]] = []
    model_numbers: Optional[List[str]] = []
    body_type_id: Optional[UUID] = None
    body_type_name: Optional[str] = None
    body_type_ids: Optional[List[UUID]] = []
    body_type_names: Optional[List[str]] = []
    checkpoint_count: Optional[int] = 0
    sort_order: int = 1
    is_mandatory: bool = True

    class Config:
        from_attributes = True

class StationMappingCreate(BaseModel):
    station_id: UUID
    template_id: UUID
    model_id: Optional[UUID] = None
    model_ids: Optional[List[UUID]] = []
    body_type_id: Optional[UUID] = None
    body_type_ids: Optional[List[UUID]] = []
    sort_order: int = 1
    is_mandatory: bool = True

class StationMappingUpdate(BaseModel):
    model_id: Optional[UUID] = None
    model_ids: Optional[List[UUID]] = None
    body_type_id: Optional[UUID] = None
    body_type_ids: Optional[List[UUID]] = None
    sort_order: Optional[int] = None
    is_mandatory: Optional[bool] = None


# ── Inspection ────────────────────────────────────────────
class InspectStartRequest(BaseModel):
    chassis_no: str
    station_id: UUID

class InspectStartResponse(BaseModel):
    chassis_id: UUID
    chassis_no: str
    station_name: str
    model_id: Optional[UUID] = None
    model_number: Optional[str] = None
    body_type_id: Optional[UUID] = None
    body_type_name: Optional[str] = None
    instances: List["InstanceSummary"]
    order_spec: Optional[Dict[str, Any]] = None

class InstanceSummary(BaseModel):
    instance_id: UUID
    template_id: UUID
    template_name: str
    template_code: str
    station_qa_status: str = "PENDING"
    total_items: int = 0
    responded_items: int = 0

class InstanceDetailOut(BaseModel):
    instance_id: UUID
    template_id: Optional[UUID] = None
    template_name: Optional[str] = ""
    chassis_no: Optional[str] = None
    station_name: Optional[str] = None
    model_number: Optional[str] = None
    body_type_name: Optional[str] = None
    format_no: Optional[str] = None
    revision: Optional[str] = None
    overall_result: Optional[str] = "PENDING"
    station_qa_status: Optional[str] = "PENDING"
    remarks: Optional[str] = None
    can_clear_chassis_out: Optional[bool] = False
    is_chassis_out_cleared: Optional[bool] = False
    chassis_out_cleared_at: Optional[datetime] = None
    sections: List["SectionWithResponses"] = []
    order_spec: Optional[Dict[str, Any]] = None

class SectionWithResponses(BaseModel):
    section_id: UUID
    section_name: Optional[str] = ""
    section_no: Optional[Union[str, int, float]] = 0
    description: Optional[str] = None
    remark: Optional[str] = None
    is_carried_forward: Optional[bool] = False
    items: List["ItemWithResponse"] = []


class SectionRemarkIn(BaseModel):
    section_id: UUID
    remark: Optional[str] = None

class InstanceRemarksIn(BaseModel):
    remarks: Optional[str] = None                 # whole checksheet
    sections: List[SectionRemarkIn] = []          # per section

class ItemWithResponse(BaseModel):
    item_id: UUID
    item_no: Optional[Union[str, int, float]] = 1
    area_desc: Optional[str] = None
    checkpoint_desc: Optional[str] = ""
    checkpoint_class: Optional[str] = "MAJOR"
    verification_method: Optional[str] = None
    standard_specification: Optional[str] = None
    requires_measurement: bool = False
    min_value: Optional[Union[Decimal, float, int, str]] = None
    max_value: Optional[Union[Decimal, float, int, str]] = None
    unit_of_measure: Optional[str] = None
    special_feature_flag: Optional[str] = None
    frequency: Optional[str] = None
    model_specs: Optional[Union[dict, list, str]] = None
    sub_points: Optional[Union[list, dict, str]] = None
    reference_diagram_url: Optional[str] = None
    response_id: Optional[UUID] = None
    status: Optional[str] = None
    measured_value: Optional[Union[Decimal, float, int, str]] = None
    sub_point_values: Optional[Union[dict, list, str]] = None
    observation: Optional[str] = None
    rework_status: Optional[str] = None
    after_rework_observation: Optional[str] = None
    is_carried_forward: Optional[bool] = False
    carried_from_station: Optional[str] = None
    original_response_id: Optional[UUID] = None
    photos: List["ResponsePhotoOut"] = []


class ResponsePhotoOut(BaseModel):
    photo_id: UUID
    photo_url: str
    uploaded_at: Optional[datetime] = None


# ── Responses ─────────────────────────────────────────────
class ResponseBulkItem(BaseModel):
    item_id: UUID
    status: str = "OK"          # OK / NOT_OK / NA
    measured_value: Optional[Decimal] = None
    sub_point_values: Optional[dict] = None
    observation: Optional[str] = None
    na_reason: Optional[str] = None
    rework_status: Optional[str] = None
    after_rework_observation: Optional[str] = None
    is_carried_forward: Optional[bool] = False
    original_response_id: Optional[UUID] = None

class ResponseBulkRequest(BaseModel):
    responses: List[ResponseBulkItem]


# ── Sign-off ──────────────────────────────────────────────
class SignoffRequest(BaseModel):
    result: str = Field(..., pattern="^(PASSED|FAILED)$")
    remarks: Optional[str] = None
    rework_notes: Optional[str] = None

class SignoffResponse(BaseModel):
    instance_id: UUID
    overall_result: str
    station_qa_status: str
    inventory_deducted: bool = False
    message: str
    all_mandatory_passed: bool = False   # every mandatory checksheet at this station has passed
    can_release: bool = False            # operator has completed, so QA may pass it to the next station
    next_station_name: Optional[str] = None


# ── Shortage ──────────────────────────────────────────────
class ShortageOut(BaseModel):
    shortage_id: UUID
    chassis_id: UUID
    station_id: UUID
    rm_id: UUID
    rm_name: Optional[str] = None
    rm_code: Optional[str] = None
    required_qty: Decimal
    fitted_qty: Decimal
    short_qty: Decimal
    status: str
    remarks: Optional[str] = None
    noted_at: Optional[datetime] = None
    resolved_at: Optional[datetime] = None

    class Config:
        from_attributes = True

class ShortageCreate(BaseModel):
    chassis_no: str
    station_id: UUID
    rm_id: UUID
    required_qty: Decimal = Decimal("1")
    fitted_qty: Decimal = Decimal("0")
    remarks: Optional[str] = None

class ShortageUpdate(BaseModel):
    fitted_qty: Optional[Decimal] = None
    remarks: Optional[str] = None


# ── Dashboard ─────────────────────────────────────────────
class QAStationSummary(BaseModel):
    station_id: UUID
    station_name: str
    pending: int = 0
    in_progress: int = 0
    passed: int = 0
    failed: int = 0

class QADashboardResponse(BaseModel):
    total_pending: int = 0
    total_passed: int = 0
    total_failed: int = 0
    stations: List[QAStationSummary] = []


# ── Chassis History ───────────────────────────────────────
class ChassisQAHistoryItem(BaseModel):
    instance_id: UUID
    template_id: UUID
    template_name: str
    template_code: str
    station_id: UUID
    station_name: str
    inspection_date: Optional[datetime] = None
    overall_result: str
    station_qa_status: str
    total_items: int = 0
    ok_items: int = 0
    not_ok_items: int = 0
    na_items: int = 0
    completed_at: Optional[datetime] = None


# ── Chassis Out Clearance ─────────────────────────────────
class ClearanceForChassisOutRequest(BaseModel):
    remarks: Optional[str] = None

class ClearanceForChassisOutResponse(BaseModel):
    status: str
    message: str
    station_name: str
    cleared_at: datetime
    cleared_by: Optional[str] = None


# ── Comprehensive Supervisor Dashboard ────────────────────
class ChassisLiveQaStatus(BaseModel):
    instance_id: Optional[UUID] = None
    chassis_id: UUID
    chassis_no: str
    model_name: Optional[str] = None
    body_type: Optional[str] = None
    customer_name: Optional[str] = None
    station_id: Optional[UUID] = None
    station_name: Optional[str] = None
    station_code: Optional[str] = None
    station_sequence: Optional[int] = None
    overall_qa_status: str = "PENDING"  # PENDING / IN_PROGRESS / PASSED / FAILED / ON_HOLD
    is_cleared: bool = False
    is_current_station: bool = False
    current_station_name: Optional[str] = None
    inspector_name: Optional[str] = None
    inspector_code: Optional[str] = None
    checkpoints_total: int = 0
    checkpoints_completed: int = 0
    defects_count: int = 0
    updated_at: Optional[datetime] = None

class DefectDetailItem(BaseModel):
    response_id: UUID
    instance_id: UUID
    chassis_no: str
    station_name: str
    checkpoint_desc: str
    checkpoint_class: str = "MAJOR"  # CRITICAL / MAJOR / MINOR
    status: str = "NOT_OK"
    measured_value: Optional[float] = None
    observation: Optional[str] = None
    inspector_name: Optional[str] = None
    inspector_code: Optional[str] = None
    photo_urls: List[str] = []
    rework_status: Optional[str] = None
    created_at: Optional[datetime] = None

class AssignedInspectorBrief(BaseModel):
    user_id: UUID
    name: str
    employee_code: Optional[str] = None
    email: Optional[str] = None

class StationAllocationItem(BaseModel):
    station_id: UUID
    station_name: str
    station_code: str
    sequence_no: Optional[int] = None
    requires_qa: bool = True
    assigned_inspectors: List[AssignedInspectorBrief] = []
    active_chassis_count: int = 0
    active_chassis_list: List[str] = []
    passed_count: int = 0
    failed_count: int = 0
    pending_count: int = 0

class SupervisorDashboardKpis(BaseModel):
    total_active_chassis: int = 0
    total_passed: int = 0
    total_failed: int = 0
    total_pending: int = 0
    total_defects: int = 0
    cleared_for_chassis_out: int = 0
    active_inspectors: int = 0
    monitored_stations: int = 0

class SupervisorDashboardResponse(BaseModel):
    kpis: SupervisorDashboardKpis
    chassis_statuses: List[ChassisLiveQaStatus] = []
    defects: List[DefectDetailItem] = []
    station_allocations: List[StationAllocationItem] = []


# ── Inspector Analytics ───────────────────────────────────
class InspectorMetricItem(BaseModel):
    user_id: UUID
    name: str
    employee_code: Optional[str] = None
    role_code: Optional[str] = None
    email: Optional[str] = None
    assigned_stations: List[str] = []
    total_inspected: int = 0
    total_passed: int = 0
    total_failed: int = 0
    pass_rate: float = 100.0
    total_checkpoints: int = 0
    total_defects: int = 0
    critical_defects: int = 0
    major_defects: int = 0
    minor_defects: int = 0
    last_active: Optional[datetime] = None

class InspectorAnalyticsSummary(BaseModel):
    total_inspectors: int = 0
    total_inspections: int = 0
    plant_pass_rate: float = 100.0
    total_defects_caught: int = 0
    critical_defects: int = 0
    major_defects: int = 0
    minor_defects: int = 0

class InspectorAnalyticsResponse(BaseModel):
    summary: InspectorAnalyticsSummary
    inspectors: List[InspectorMetricItem] = []

