"""
GASKET 분류 시스템
플랜지용 가스켓 및 씰링 제품 분류
"""

import re
from typing import Dict, List, Optional
from .material_classifier import classify_material

# ========== 가스켓 타입별 분류 ==========
GASKET_TYPES = {
    "SPIRAL_WOUND": {
        "dat_file_patterns": ["SWG_", "SPIRAL_"],
        "description_keywords": ["SPIRAL WOUND", "SPIRAL", "스파이럴", "SWG"],
        "characteristics": "금속 스트립과 필러의 나선형 조합",
        "pressure_range": "150LB ~ 2500LB",
        "temperature_range": "-200°C ~ 800°C",
        "applications": "고온고압, 일반 산업용"
    },
    
    "RING_JOINT": {
        "dat_file_patterns": ["RTJ_", "RJ_", "RING_"],
        "description_keywords": ["RING JOINT", "RTJ", "RING TYPE JOINT", "링조인트"],
        "characteristics": "금속 링 형태의 고압용 가스켓",
        "pressure_range": "600LB ~ 2500LB",
        "temperature_range": "-100°C ~ 650°C",
        "applications": "고압 플랜지 전용"
    },
    
    "FULL_FACE": {
        "dat_file_patterns": ["FF_", "FULL_"],
        "description_keywords": ["FULL FACE", "FF", "풀페이스"],
        "characteristics": "플랜지 전면 커버 가스켓",
        "pressure_range": "150LB ~ 300LB",
        "temperature_range": "-50°C ~ 400°C",
        "applications": "평면 플랜지용"
    },
    
    "RAISED_FACE": {
        "dat_file_patterns": ["RF_", "RAISED_"],
        "description_keywords": ["RAISED FACE", "RF", "레이즈드"],
        "characteristics": "볼록한 면 전용 가스켓",
        "pressure_range": "150LB ~ 600LB",
        "temperature_range": "-50°C ~ 450°C",
        "applications": "일반 볼록면 플랜지용"
    },
    
    "O_RING": {
        "dat_file_patterns": ["OR_", "ORING_"],
        "description_keywords": ["O-RING", "O RING", "ORING", "오링"],
        "characteristics": "원형 단면의 씰링 링",
        "pressure_range": "저압 ~ 고압 (재질별)",
        "temperature_range": "-60°C ~ 300°C (재질별)",
        "applications": "홈 씰링, 회전축 씰링"
    },
    
    "SHEET_GASKET": {
        "dat_file_patterns": ["SHEET_", "SHT_"],
        "description_keywords": ["SHEET GASKET", "SHEET", "시트"],
        "characteristics": "판 형태의 가스켓",
        "pressure_range": "150LB ~ 600LB",
        "temperature_range": "-50°C ~ 500°C",
        "applications": "일반 플랜지, 맨홀"
    },
    
    "KAMMPROFILE": {
        "dat_file_patterns": ["KAMM_", "KP_"],
        "description_keywords": ["KAMMPROFILE", "KAMM", "캄프로파일"],
        "characteristics": "파형 금속에 소프트 코팅",
        "pressure_range": "150LB ~ 1500LB",
        "temperature_range": "-200°C ~ 700°C",
        "applications": "고온고압, 화학공정"
    },
    
    "CUSTOM_GASKET": {
        "dat_file_patterns": ["CUSTOM_", "SPEC_"],
        "description_keywords": ["CUSTOM", "SPECIAL", "특주", "맞춤"],
        "characteristics": "특수 제작 가스켓",
        "pressure_range": "요구사항별",
        "temperature_range": "요구사항별",
        "applications": "특수 형상, 특수 조건"
    }
}

# ========== 가스켓 재질별 분류 ==========
GASKET_MATERIALS = {
    "GRAPHITE": {
        "keywords": ["GRAPHITE", "그라파이트", "흑연"],
        "characteristics": "고온 내성, 화학 안정성",
        "temperature_range": "-200°C ~ 650°C",
        "applications": "고온 스팀, 화학공정"
    },
    
    "PTFE": {
        "keywords": ["PTFE", "TEFLON", "테프론"],
        "characteristics": "화학 내성, 낮은 마찰",
        "temperature_range": "-200°C ~ 260°C",
        "applications": "화학공정, 식품용"
    },
    
    "VITON": {
        "keywords": ["VITON", "FKM", "바이톤"],
        "characteristics": "유류 내성, 고온 내성",
        "temperature_range": "-20°C ~ 200°C",
        "applications": "유류, 고온 가스"
    },
    
    "EPDM": {
        "keywords": ["EPDM", "이피디엠"],
        "characteristics": "일반 고무, 스팀 내성",
        "temperature_range": "-50°C ~ 150°C",
        "applications": "스팀, 일반용"
    },
    
    "NBR": {
        "keywords": ["NBR", "NITRILE", "니트릴"],
        "characteristics": "유류 내성",
        "temperature_range": "-30°C ~ 100°C",
        "applications": "유압, 윤활유"
    },
    
    "METAL": {
        "keywords": ["METAL", "SS", "STAINLESS", "금속"],
        "characteristics": "고온고압 내성",
        "temperature_range": "-200°C ~ 800°C",
        "applications": "극한 조건"
    },
    
    "COMPOSITE": {
        "keywords": ["COMPOSITE", "복합재", "FIBER"],
        "characteristics": "다층 구조",
        "temperature_range": "재질별 상이",
        "applications": "특수 조건"
    }
}

# ========== 압력 등급별 분류 ==========
GASKET_PRESSURE_RATINGS = {
    "patterns": [
        r"(\d+)LB",
        r"CLASS\s*(\d+)",
        r"CL\s*(\d+)",
        r"(\d+)#"
    ],
    "standard_ratings": {
        "150LB": {"max_pressure": "285 PSI", "typical_gasket": "SHEET, SPIRAL_WOUND"},
        "300LB": {"max_pressure": "740 PSI", "typical_gasket": "SPIRAL_WOUND, SHEET"},
        "600LB": {"max_pressure": "1480 PSI", "typical_gasket": "SPIRAL_WOUND, RTJ"},
        "900LB": {"max_pressure": "2220 PSI", "typical_gasket": "SPIRAL_WOUND, RTJ"},
        "1500LB": {"max_pressure": "3705 PSI", "typical_gasket": "RTJ, SPIRAL_WOUND"},
        "2500LB": {"max_pressure": "6170 PSI", "typical_gasket": "RTJ"}
    }
}

# ========== 사이즈 표기법 ==========
GASKET_SIZE_PATTERNS = {
    "flange_size": r"(\d+(?:\.\d+)?)\s*[\"\'']?\s*(?:INCH|IN|인치)?",
    "inner_diameter": r"ID\s*(\d+(?:\.\d+)?)",
    "outer_diameter": r"OD\s*(\d+(?:\.\d+)?)",
    "thickness": r"THK?\s*(\d+(?:\.\d+)?)\s*MM"
}

def classify_gasket(dat_file: str, description: str, main_nom: str, length: float = None) -> Dict:
    """
    완전한 GASKET 분류
    
    Args:
        dat_file: DAT_FILE 필드
        description: DESCRIPTION 필드
        main_nom: MAIN_NOM 필드 (플랜지 사이즈)
    
    Returns:
        완전한 가스켓 분류 결과
    """
    
    # 1. 재질 분류 (공통 모듈 + 가스켓 전용)
    material_result = classify_material(description)
    gasket_material_result = classify_gasket_material(description)
    
    # 2. 가스켓 타입 분류
    gasket_type_result = classify_gasket_type(dat_file, description)
    
    # 3. 압력 등급 분류
    pressure_result = classify_gasket_pressure_rating(dat_file, description)
    
    # 4. 사이즈 정보 추출
    size_result = extract_gasket_size_info(main_nom, description)
    
    # 5. 온도 범위 추출
    temperature_result = extract_temperature_range(description, gasket_type_result, gasket_material_result)
    
    # 6. 최종 결과 조합
    return {
        "category": "GASKET",
        
        # 재질 정보 (공통 + 가스켓 전용)
        "material": {
            "standard": material_result.get('standard', 'UNKNOWN'),
            "grade": material_result.get('grade', 'UNKNOWN'),
            "material_type": material_result.get('material_type', 'UNKNOWN'),
            "confidence": material_result.get('confidence', 0.0)
        },
        
        "gasket_material": {
            "material": gasket_material_result.get('material', 'UNKNOWN'),
            "characteristics": gasket_material_result.get('characteristics', ''),
            "temperature_range": gasket_material_result.get('temperature_range', ''),
            "confidence": gasket_material_result.get('confidence', 0.0),
            "swg_details": gasket_material_result.get('swg_details', {})
        },
        
        # 가스켓 분류 정보
        "gasket_type": {
            "type": gasket_type_result.get('type', 'UNKNOWN'),
            "characteristics": gasket_type_result.get('characteristics', ''),
            "confidence": gasket_type_result.get('confidence', 0.0),
            "evidence": gasket_type_result.get('evidence', []),
            "pressure_range": gasket_type_result.get('pressure_range', ''),
            "applications": gasket_type_result.get('applications', '')
        },
        
        "pressure_rating": {
            "rating": pressure_result.get('rating', 'UNKNOWN'),
            "confidence": pressure_result.get('confidence', 0.0),
            "max_pressure": pressure_result.get('max_pressure', ''),
            "typical_gasket": pressure_result.get('typical_gasket', '')
        },
        
        "size_info": {
            "flange_size": size_result.get('flange_size', main_nom),
            "inner_diameter": size_result.get('inner_diameter', ''),
            "outer_diameter": size_result.get('outer_diameter', ''),
            "thickness": size_result.get('thickness', ''),
            "size_description": size_result.get('size_description', main_nom)
        },
        
        "temperature_info": {
            "range": temperature_result.get('range', ''),
            "max_temp": temperature_result.get('max_temp', ''),
            "min_temp": temperature_result.get('min_temp', ''),
            "confidence": temperature_result.get('confidence', 0.0)
        },
        
        # 전체 신뢰도
        "overall_confidence": calculate_gasket_confidence({
            "gasket_type": gasket_type_result.get('confidence', 0),
            "gasket_material": gasket_material_result.get('confidence', 0),
            "pressure": pressure_result.get('confidence', 0),
            "size": size_result.get('confidence', 0.8)  # 기본 신뢰도
        })
    }

def classify_gasket_type(dat_file: str, description: str) -> Dict:
    """가스켓 타입 분류"""
    
    dat_upper = dat_file.upper()
    desc_upper = description.upper()
    
    # 1. DAT_FILE 패턴으로 1차 분류
    for gasket_type, type_data in GASKET_TYPES.items():
        for pattern in type_data["dat_file_patterns"]:
            if pattern in dat_upper:
                return {
                    "type": gasket_type,
                    "characteristics": type_data["characteristics"],
                    "confidence": 0.95,
                    "evidence": [f"DAT_FILE_PATTERN: {pattern}"],
                    "pressure_range": type_data["pressure_range"],
                    "temperature_range": type_data["temperature_range"],
                    "applications": type_data["applications"]
                }
    
    # 2. DESCRIPTION 키워드로 2차 분류
    for gasket_type, type_data in GASKET_TYPES.items():
        for keyword in type_data["description_keywords"]:
            if keyword in desc_upper:
                return {
                    "type": gasket_type,
                    "characteristics": type_data["characteristics"],
                    "confidence": 0.85,
                    "evidence": [f"DESCRIPTION_KEYWORD: {keyword}"],
                    "pressure_range": type_data["pressure_range"],
                    "temperature_range": type_data["temperature_range"],
                    "applications": type_data["applications"]
                }
    
    # 3. 분류 실패
    return {
        "type": "UNKNOWN",
        "characteristics": "",
        "confidence": 0.0,
        "evidence": ["NO_GASKET_TYPE_IDENTIFIED"],
        "pressure_range": "",
        "temperature_range": "",
        "applications": ""
    }

def parse_swg_details(description: str) -> Dict:
    """SWG (Spiral Wound Gasket) 상세 정보 파싱"""
    
    desc_upper = description.upper()
    result = {
        "face_type": "UNKNOWN",
        "outer_ring": "UNKNOWN", 
        "filler": "UNKNOWN",
        "inner_ring": "UNKNOWN",
        "thickness": None,
        "detailed_construction": "",
        "confidence": 0.0
    }
    
    # H/F/I/O 패턴 파싱 (Head/Face/Inner/Outer)
    hfio_pattern = r'H/F/I/O|HFIO'
    if re.search(hfio_pattern, desc_upper):
        result["face_type"] = "H/F/I/O"
        result["confidence"] += 0.3
    
    # 재질 구성 파싱 (SS304/GRAPHITE/CS/CS)
    # H/F/I/O 다음에 나오는 재질 구성을 찾음
    material_pattern = r'H/F/I/O\s+([A-Z0-9]+)/([A-Z]+)/([A-Z0-9]+)/([A-Z0-9]+)'
    material_match = re.search(material_pattern, desc_upper)
    if material_match:
        result["outer_ring"] = material_match.group(1)  # SS304
        result["filler"] = material_match.group(2)      # GRAPHITE  
        result["inner_ring"] = material_match.group(3)  # CS
        # 네 번째는 보통 outer ring 반복
        result["detailed_construction"] = f"{material_match.group(1)}/{material_match.group(2)}/{material_match.group(3)}/{material_match.group(4)}"
        result["confidence"] += 0.4
    else:
        # H/F/I/O 없이 재질만 있는 경우
        material_pattern_simple = r'([A-Z0-9]+)/([A-Z]+)/([A-Z0-9]+)/([A-Z0-9]+)'
        material_match = re.search(material_pattern_simple, desc_upper)
        if material_match:
            result["outer_ring"] = material_match.group(1)
            result["filler"] = material_match.group(2)
            result["inner_ring"] = material_match.group(3)
            result["detailed_construction"] = f"{material_match.group(1)}/{material_match.group(2)}/{material_match.group(3)}/{material_match.group(4)}"
            result["confidence"] += 0.3
    
    # 두께 파싱 (4.5mm)
    thickness_pattern = r'(\d+(?:\.\d+)?)\s*MM'
    thickness_match = re.search(thickness_pattern, desc_upper)
    if thickness_match:
        result["thickness"] = float(thickness_match.group(1))
        result["confidence"] += 0.3
    
    return result

def classify_gasket_material(description: str) -> Dict:
    """가스켓 전용 재질 분류 (SWG 상세 정보 포함)"""
    
    desc_upper = description.upper()
    
    # SWG 상세 정보 파싱
    swg_details = None
    if "SWG" in desc_upper or "SPIRAL WOUND" in desc_upper:
        swg_details = parse_swg_details(description)
    
    # 기본 가스켓 재질 확인
    for material_type, material_data in GASKET_MATERIALS.items():
        for keyword in material_data["keywords"]:
            if keyword in desc_upper:
                result = {
                    "material": material_type,
                    "characteristics": material_data["characteristics"],
                    "temperature_range": material_data["temperature_range"],
                    "confidence": 0.9,
                    "matched_keyword": keyword,
                    "applications": material_data["applications"]
                }
                
                # SWG 상세 정보 추가
                if swg_details and swg_details["confidence"] > 0:
                    result["swg_details"] = swg_details
                    result["confidence"] = min(0.95, result["confidence"] + swg_details["confidence"] * 0.1)
                
                return result
    
    # 일반 재질 키워드 확인
    if any(keyword in desc_upper for keyword in ["RUBBER", "고무"]):
        return {
            "material": "RUBBER",
            "characteristics": "일반 고무계",
            "temperature_range": "-50°C ~ 100°C",
            "confidence": 0.7,
            "matched_keyword": "RUBBER",
            "applications": "일반용"
        }
    
    return {
        "material": "UNKNOWN",
        "characteristics": "",
        "temperature_range": "",
        "confidence": 0.0,
        "matched_keyword": "",
        "applications": ""
    }

def classify_gasket_pressure_rating(dat_file: str, description: str) -> Dict:
    """가스켓 압력 등급 분류"""
    
    combined_text = f"{dat_file} {description}".upper()
    
    # 패턴 매칭으로 압력 등급 추출
    for pattern in GASKET_PRESSURE_RATINGS["patterns"]:
        match = re.search(pattern, combined_text)
        if match:
            rating_num = match.group(1)
            rating = f"{rating_num}LB"
            
            # 표준 등급 정보 확인
            rating_info = GASKET_PRESSURE_RATINGS["standard_ratings"].get(rating, {})
            
            if rating_info:
                confidence = 0.95
            else:
                confidence = 0.8
                rating_info = {
                    "max_pressure": "확인 필요",
                    "typical_gasket": "확인 필요"
                }
            
            return {
                "rating": rating,
                "confidence": confidence,
                "matched_pattern": pattern,
                "matched_value": rating_num,
                "max_pressure": rating_info.get("max_pressure", ""),
                "typical_gasket": rating_info.get("typical_gasket", "")
            }
    
    return {
        "rating": "UNKNOWN",
        "confidence": 0.0,
        "matched_pattern": "",
        "max_pressure": "",
        "typical_gasket": ""
    }

def extract_gasket_size_info(main_nom: str, description: str) -> Dict:
    """가스켓 사이즈 정보 추출"""
    
    desc_upper = description.upper()
    size_info = {
        "flange_size": main_nom,
        "inner_diameter": "",
        "outer_diameter": "", 
        "thickness": "",
        "size_description": main_nom,
        "confidence": 0.8
    }
    
    # 내경(ID) 추출
    id_match = re.search(GASKET_SIZE_PATTERNS["inner_diameter"], desc_upper)
    if id_match:
        size_info["inner_diameter"] = f"{id_match.group(1)}mm"
    
    # 외경(OD) 추출
    od_match = re.search(GASKET_SIZE_PATTERNS["outer_diameter"], desc_upper)
    if od_match:
        size_info["outer_diameter"] = f"{od_match.group(1)}mm"
    
    # 두께(THK) 추출
    thk_match = re.search(GASKET_SIZE_PATTERNS["thickness"], desc_upper)
    if thk_match:
        size_info["thickness"] = f"{thk_match.group(1)}mm"
    
    # 사이즈 설명 조합
    size_parts = [main_nom]
    if size_info["inner_diameter"] and size_info["outer_diameter"]:
        size_parts.append(f"ID{size_info['inner_diameter']}")
        size_parts.append(f"OD{size_info['outer_diameter']}")
    if size_info["thickness"]:
        size_parts.append(f"THK{size_info['thickness']}")
    
    size_info["size_description"] = " ".join(size_parts)
    
    return size_info

def extract_temperature_range(description: str, gasket_type_result: Dict, 
                            gasket_material_result: Dict) -> Dict:
    """온도 범위 정보 추출"""
    
    desc_upper = description.upper()
    
    # DESCRIPTION에서 직접 온도 추출
    temp_patterns = [
        r'(\-?\d+(?:\.\d+)?)\s*°?C\s*~\s*(\-?\d+(?:\.\d+)?)\s*°?C',
        r'(\-?\d+(?:\.\d+)?)\s*TO\s*(\-?\d+(?:\.\d+)?)\s*°?C',
        r'MAX\s*(\-?\d+(?:\.\d+)?)\s*°?C',
        r'MIN\s*(\-?\d+(?:\.\d+)?)\s*°?C'
    ]
    
    for pattern in temp_patterns:
        match = re.search(pattern, desc_upper)
        if match:
            if len(match.groups()) == 2:  # 범위
                return {
                    "range": f"{match.group(1)}°C ~ {match.group(2)}°C",
                    "min_temp": f"{match.group(1)}°C",
                    "max_temp": f"{match.group(2)}°C",
                    "confidence": 0.95,
                    "source": "DESCRIPTION_RANGE"
                }
            else:  # 단일 온도
                temp_value = match.group(1)
                if "MAX" in pattern:
                    return {
                        "range": f"~ {temp_value}°C",
                        "max_temp": f"{temp_value}°C",
                        "confidence": 0.9,
                        "source": "DESCRIPTION_MAX"
                    }
    
    # 가스켓 재질 기반 온도 범위
    material_temp = gasket_material_result.get('temperature_range', '')
    if material_temp:
        return {
            "range": material_temp,
            "confidence": 0.8,
            "source": "MATERIAL_BASED"
        }
    
    # 가스켓 타입 기반 온도 범위
    type_temp = gasket_type_result.get('temperature_range', '')
    if type_temp:
        return {
            "range": type_temp,
            "confidence": 0.7,
            "source": "TYPE_BASED"
        }
    
    return {
        "range": "",
        "confidence": 0.0,
        "source": "NO_TEMPERATURE_INFO"
    }

def calculate_gasket_confidence(confidence_scores: Dict) -> float:
    """가스켓 분류 전체 신뢰도 계산"""
    
    scores = [score for score in confidence_scores.values() if score > 0]
    
    if not scores:
        return 0.0
    
    # 가중 평균
    weights = {
        "gasket_type": 0.4,
        "gasket_material": 0.3,
        "pressure": 0.2,
        "size": 0.1
    }
    
    weighted_sum = sum(
        confidence_scores.get(key, 0) * weight
        for key, weight in weights.items()
    )
    
    return round(weighted_sum, 2)

# ========== 특수 기능들 ==========

def get_gasket_purchase_info(gasket_result: Dict) -> Dict:
    """가스켓 구매 정보 생성"""
    
    gasket_type = gasket_result["gasket_type"]["type"]
    gasket_material = gasket_result["gasket_material"]["material"]
    pressure = gasket_result["pressure_rating"]["rating"]
    
    # 공급업체 타입 결정
    if gasket_type == "CUSTOM_GASKET":
        supplier_type = "특수 가스켓 제작업체"
    elif gasket_material in ["GRAPHITE", "PTFE"]:
        supplier_type = "고급 씰링 전문업체"
    elif gasket_type in ["SPIRAL_WOUND", "RING_JOINT"]:
        supplier_type = "산업용 가스켓 전문업체"
    else:
        supplier_type = "일반 가스켓 업체"
    
    # 납기 추정
    if gasket_type == "CUSTOM_GASKET":
        lead_time = "4-8주 (특수 제작)"
    elif gasket_type in ["SPIRAL_WOUND", "KAMMPROFILE"]:
        lead_time = "2-4주 (제작품)"
    else:
        lead_time = "1-2주 (재고품)"
    
    # 구매 단위
    if gasket_type == "O_RING":
        purchase_unit = "EA (개별)"
    elif gasket_type == "SHEET_GASKET":
        purchase_unit = "SHEET (시트)"
    else:
        purchase_unit = "SET (세트)"
    
    return {
        "supplier_type": supplier_type,
        "lead_time_estimate": lead_time,
        "purchase_category": f"{gasket_type} {pressure}",
        "purchase_unit": purchase_unit,
        "material_note": gasket_result["gasket_material"]["characteristics"],
        "temperature_note": gasket_result["temperature_info"]["range"],
        "applications": gasket_result["gasket_type"]["applications"]
    }

def is_high_temperature_gasket(gasket_result: Dict) -> bool:
    """고온용 가스켓 여부 판단"""
    temp_range = gasket_result.get("temperature_info", {}).get("range", "")
    return any(indicator in temp_range for indicator in ["500°C", "600°C", "700°C", "800°C"])

def is_high_pressure_gasket(gasket_result: Dict) -> bool:
    """고압용 가스켓 여부 판단"""
    pressure_rating = gasket_result.get("pressure_rating", {}).get("rating", "")
    high_pressure_ratings = ["600LB", "900LB", "1500LB", "2500LB"]
    return any(pressure in pressure_rating for pressure in high_pressure_ratings)
