"""
API 응답 모델 정의
타입 안정성 및 API 문서화를 위한 Pydantic 모델들
"""
from pydantic import BaseModel, Field, ConfigDict
from typing import List, Optional, Dict, Any, Union
from datetime import datetime
from enum import Enum


# ================================
# 기본 응답 모델
# ================================

class BaseResponse(BaseModel):
    """기본 응답 모델"""
    success: bool = Field(description="요청 성공 여부")
    message: Optional[str] = Field(None, description="응답 메시지")
    timestamp: datetime = Field(default_factory=datetime.now, description="응답 시간")


class ErrorResponse(BaseResponse):
    """에러 응답 모델"""
    success: bool = Field(False, description="요청 성공 여부")
    error: Dict[str, Any] = Field(description="에러 정보")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "success": False,
                "message": "요청 처리 중 오류가 발생했습니다",
                "error": {
                    "code": "VALIDATION_ERROR",
                    "details": "입력 데이터가 올바르지 않습니다"
                },
                "timestamp": "2025-01-01T12:00:00"
            }
        }
    )


class SuccessResponse(BaseResponse):
    """성공 응답 모델"""
    success: bool = Field(True, description="요청 성공 여부")
    data: Optional[Any] = Field(None, description="응답 데이터")


# ================================
# 열거형 정의
# ================================

class FileStatus(str, Enum):
    """파일 상태"""
    ACTIVE = "active"
    INACTIVE = "inactive"
    PROCESSING = "processing"
    ERROR = "error"


class MaterialCategory(str, Enum):
    """자재 카테고리"""
    PIPE = "PIPE"
    FITTING = "FITTING"
    VALVE = "VALVE"
    FLANGE = "FLANGE"
    BOLT = "BOLT"
    GASKET = "GASKET"
    INSTRUMENT = "INSTRUMENT"
    EXCLUDE = "EXCLUDE"


class JobStatus(str, Enum):
    """작업 상태"""
    ACTIVE = "active"
    COMPLETED = "completed"
    ON_HOLD = "on_hold"
    CANCELLED = "cancelled"


# ================================
# 파일 관련 모델
# ================================

class FileInfo(BaseModel):
    """파일 정보 모델"""
    id: int = Field(description="파일 ID")
    filename: str = Field(description="파일명")
    original_filename: str = Field(description="원본 파일명")
    job_no: Optional[str] = Field(None, description="작업 번호")
    bom_name: Optional[str] = Field(None, description="BOM 이름")
    revision: str = Field(default="Rev.0", description="리비전")
    parsed_count: int = Field(default=0, description="파싱된 자재 수")
    bom_type: str = Field(default="unknown", description="BOM 타입")
    status: FileStatus = Field(description="파일 상태")
    file_size: Optional[int] = Field(None, description="파일 크기 (bytes)")
    upload_date: datetime = Field(description="업로드 일시")
    description: Optional[str] = Field(None, description="파일 설명")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "id": 1,
                "filename": "BOM_Rev1.xlsx",
                "original_filename": "BOM_Rev1.xlsx",
                "job_no": "TK-2025-001",
                "bom_name": "메인 BOM",
                "revision": "Rev.1",
                "parsed_count": 150,
                "bom_type": "excel",
                "status": "active",
                "file_size": 2048576,
                "upload_date": "2025-01-01T12:00:00",
                "description": "파일: BOM_Rev1.xlsx"
            }
        }
    )


class FileListResponse(BaseResponse):
    """파일 목록 응답 모델"""
    success: bool = Field(True, description="요청 성공 여부")
    data: List[FileInfo] = Field(description="파일 목록")
    total_count: int = Field(description="전체 파일 수")
    cache_hit: bool = Field(default=False, description="캐시 히트 여부")


class FileDeleteResponse(BaseResponse):
    """파일 삭제 응답 모델"""
    success: bool = Field(True, description="삭제 성공 여부")
    message: str = Field(description="삭제 결과 메시지")
    deleted_file_id: int = Field(description="삭제된 파일 ID")


# ================================
# 자재 관련 모델
# ================================

class MaterialInfo(BaseModel):
    """자재 정보 모델"""
    id: int = Field(description="자재 ID")
    file_id: int = Field(description="파일 ID")
    line_number: Optional[int] = Field(None, description="엑셀 행 번호")
    original_description: str = Field(description="원본 품명")
    classified_category: Optional[MaterialCategory] = Field(None, description="분류된 카테고리")
    classified_subcategory: Optional[str] = Field(None, description="세부 분류")
    material_grade: Optional[str] = Field(None, description="재질 등급")
    schedule: Optional[str] = Field(None, description="스케줄")
    size_spec: Optional[str] = Field(None, description="사이즈 규격")
    quantity: float = Field(description="수량")
    unit: str = Field(description="단위")
    classification_confidence: Optional[float] = Field(None, description="분류 신뢰도")
    is_verified: bool = Field(default=False, description="검증 여부")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "id": 1,
                "file_id": 1,
                "line_number": 5,
                "original_description": "PIPE, SEAMLESS, A333-6, 6\", SCH40",
                "classified_category": "PIPE",
                "classified_subcategory": "SEAMLESS",
                "material_grade": "A333-6",
                "schedule": "SCH40",
                "size_spec": "6\"",
                "quantity": 12.5,
                "unit": "EA",
                "classification_confidence": 0.95,
                "is_verified": False
            }
        }
    )


class MaterialListResponse(BaseResponse):
    """자재 목록 응답 모델"""
    success: bool = Field(True, description="요청 성공 여부")
    data: List[MaterialInfo] = Field(description="자재 목록")
    total_count: int = Field(description="전체 자재 수")
    file_info: Optional[FileInfo] = Field(None, description="파일 정보")
    cache_hit: bool = Field(default=False, description="캐시 히트 여부")


# ================================
# 작업 관련 모델
# ================================

class JobInfo(BaseModel):
    """작업 정보 모델"""
    job_no: str = Field(description="작업 번호")
    job_name: str = Field(description="작업명")
    client_name: Optional[str] = Field(None, description="고객사명")
    end_user: Optional[str] = Field(None, description="최종 사용자")
    epc_company: Optional[str] = Field(None, description="EPC 회사")
    status: JobStatus = Field(description="작업 상태")
    created_at: datetime = Field(description="생성 일시")
    file_count: int = Field(default=0, description="파일 수")
    material_count: int = Field(default=0, description="자재 수")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "job_no": "TK-2025-001",
                "job_name": "석유화학 플랜트 배관 프로젝트",
                "client_name": "한국석유화학",
                "end_user": "울산공장",
                "epc_company": "현대엔지니어링",
                "status": "active",
                "created_at": "2025-01-01T09:00:00",
                "file_count": 3,
                "material_count": 450
            }
        }
    )


class JobListResponse(BaseResponse):
    """작업 목록 응답 모델"""
    success: bool = Field(True, description="요청 성공 여부")
    data: List[JobInfo] = Field(description="작업 목록")
    total_count: int = Field(description="전체 작업 수")
    cache_hit: bool = Field(default=False, description="캐시 히트 여부")


# ================================
# 분류 관련 모델
# ================================

class ClassificationResult(BaseModel):
    """분류 결과 모델"""
    category: MaterialCategory = Field(description="분류된 카테고리")
    subcategory: Optional[str] = Field(None, description="세부 분류")
    confidence: float = Field(description="분류 신뢰도 (0.0-1.0)")
    material_grade: Optional[str] = Field(None, description="재질 등급")
    size_spec: Optional[str] = Field(None, description="사이즈 규격")
    schedule: Optional[str] = Field(None, description="스케줄")
    details: Optional[Dict[str, Any]] = Field(None, description="분류 상세 정보")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "category": "PIPE",
                "subcategory": "SEAMLESS",
                "confidence": 0.95,
                "material_grade": "A333-6",
                "size_spec": "6\"",
                "schedule": "SCH40",
                "details": {
                    "matched_keywords": ["PIPE", "SEAMLESS", "A333-6"],
                    "size_detected": True,
                    "material_detected": True
                }
            }
        }
    )


class ClassificationResponse(BaseResponse):
    """분류 응답 모델"""
    success: bool = Field(True, description="분류 성공 여부")
    data: ClassificationResult = Field(description="분류 결과")
    processing_time: float = Field(description="처리 시간 (초)")
    cache_hit: bool = Field(default=False, description="캐시 히트 여부")


# ================================
# 통계 관련 모델
# ================================

class MaterialStatistics(BaseModel):
    """자재 통계 모델"""
    category: MaterialCategory = Field(description="자재 카테고리")
    count: int = Field(description="개수")
    percentage: float = Field(description="비율 (%)")
    total_quantity: float = Field(description="총 수량")
    unique_items: int = Field(description="고유 항목 수")


class ProjectStatistics(BaseModel):
    """프로젝트 통계 모델"""
    job_no: str = Field(description="작업 번호")
    total_materials: int = Field(description="총 자재 수")
    total_files: int = Field(description="총 파일 수")
    category_breakdown: List[MaterialStatistics] = Field(description="카테고리별 분석")
    classification_accuracy: float = Field(description="분류 정확도")
    verified_percentage: float = Field(description="검증 완료율")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "job_no": "TK-2025-001",
                "total_materials": 450,
                "total_files": 3,
                "category_breakdown": [
                    {
                        "category": "PIPE",
                        "count": 180,
                        "percentage": 40.0,
                        "total_quantity": 1250.5,
                        "unique_items": 45
                    }
                ],
                "classification_accuracy": 0.92,
                "verified_percentage": 0.75
            }
        }
    )


class StatisticsResponse(BaseResponse):
    """통계 응답 모델"""
    success: bool = Field(True, description="요청 성공 여부")
    data: ProjectStatistics = Field(description="통계 데이터")
    cache_hit: bool = Field(default=False, description="캐시 히트 여부")


# ================================
# 시스템 관련 모델
# ================================

class CacheInfo(BaseModel):
    """캐시 정보 모델"""
    status: str = Field(description="캐시 상태")
    used_memory: str = Field(description="사용 메모리")
    connected_clients: int = Field(description="연결된 클라이언트 수")
    hit_rate: float = Field(description="캐시 히트율 (%)")
    total_commands: int = Field(description="총 명령 수")


class SystemHealthResponse(BaseResponse):
    """시스템 상태 응답 모델"""
    success: bool = Field(True, description="요청 성공 여부")
    data: Dict[str, Any] = Field(description="시스템 상태 정보")
    cache_info: Optional[CacheInfo] = Field(None, description="캐시 정보")
    database_status: str = Field(description="데이터베이스 상태")
    api_version: str = Field(description="API 버전")


# ================================
# 유니온 타입 (여러 응답 타입)
# ================================

# API 응답으로 사용할 수 있는 모든 타입
APIResponse = Union[
    SuccessResponse,
    ErrorResponse,
    FileListResponse,
    FileDeleteResponse,
    MaterialListResponse,
    JobListResponse,
    ClassificationResponse,
    StatisticsResponse,
    SystemHealthResponse
]
