"""DXF 파일명에서 구조물 종류를 자동 추정.

토목 설계 도면 파일명에는 보통 구조물 종류가 포함됨:
  "여수로 수문 설치도.dxf" → spillway_gate
  "좌안옹벽 일반도.dxf" → retaining_wall
  "신설 취수탑 설비 설치도.dxf" → building
  "OO 교량 상세도.dxf" → bridge
  "터널 갱구 설치도.dxf" → tunnel_portal

사용법:
    from filename_classifier import classify_by_filename
    tid = classify_by_filename("좌안옹벽 일반도.dxf")
    # → "retaining_wall"
"""

from __future__ import annotations

import re
from pathlib import Path


# ---------------------------------------------------------------------------
# 구조물 유형별 키워드 패턴
# ---------------------------------------------------------------------------
# 우선순위가 높은 것을 먼저 (더 구체적인 패턴 → 일반적인 패턴)

FILENAME_PATTERNS = {
    "spillway_gate": [
        # 여수로 수문 관련
        r"여수로.*수문",
        r"수문.*여수로",
        r"여수로.*게이트",
        r"래디얼.*게이트",
        r"테인터.*게이트",
        r"tainter.*gate",
        r"radial.*gate",
        r"spillway.*gate",
        r"spillway",
        # 수문 단독
        r"(?<![\uAC00-\uD7A3])수문(?![\uAC00-\uD7A3])",  # 한글 경계
        r"gate\b",
    ],

    "retaining_wall": [
        r"옹벽",
        r"방벽",
        r"(?:좌안|우안).*옹벽",
        r"retaining.*wall",
        r"\bwall\b(?!.*gate)",  # wall but not "gate wall" etc.
    ],

    "bridge": [
        r"교량",
        r"공도교",
        r"연륙교",
        r"인도교",
        r"bridge",
        r"(?<![가-힣a-z])교(?:\s|\.|_|$)",  # 단독 "교"
        r"viaduct",
        r"overpass",
    ],

    "tunnel_portal": [
        r"터널",
        r"갱구",
        r"tunnel",
        r"portal",
        r"굴착.*입구",
    ],

    "intake_tower": [
        r"취수탑",
        r"intake.*tower",
        r"intake.*structure",
    ],

    "valve_chamber": [
        r"제수변실",
        r"밸브실",
        r"변실",
        r"valve.*(?:room|chamber)",
        r"도수관로",
        r"도수.*관",
    ],

    "building": [
        # 일반 건축물
        r"관리사무",
        r"사무소",
        r"관리동",
        r"수문조작실",
        r"변전소",
        r"기계실",
        r"전기실",
        r"건축물",
        r"건물",
        r"building",
        r"office",
        r"powerhouse",
        r"발전소",
        r"펌프장",
        r"pump(?:ing)?.*station",
        r"조정지",
    ],

    # Generic은 마지막 폴백이므로 패턴 없음
}

# 구조물 종류 힌트가 될 수 있는 추가 키워드 (신뢰도 낮음)
SECONDARY_KEYWORDS = {
    "spillway_gate": ["스필웨이", "월류", "유수전환", "가물막이", "cofferdam"],
    "retaining_wall": ["절토", "성토사면", "법면"],
    "bridge": ["교대", "교각", "상판", "pier", "abutment", "deck"],
    "tunnel_portal": ["터파기", "갱내"],
    "building": ["사택", "청사", "센터"],
}


# ---------------------------------------------------------------------------
# 분류 함수
# ---------------------------------------------------------------------------

def classify_by_filename(filename: str) -> str | None:
    """파일명에서 구조물 유형을 추정.

    Args:
        filename: 파일 경로 또는 파일명

    Returns:
        template_id 문자열 ("spillway_gate", "building" 등) 또는
        확실한 매칭이 없으면 None
    """
    # 파일명만 추출 (경로/확장자 제거)
    name = Path(filename).stem.lower()

    # 구두점/숫자 코드 노이즈 제거 (예: "12995740-M40-001")
    # 한글/영문 단어만 남김
    cleaned = re.sub(r"[\d\-_/\\]+", " ", name)
    cleaned = re.sub(r"\s+", " ", cleaned).strip()

    # 주 키워드 우선 매칭
    for template_id, patterns in FILENAME_PATTERNS.items():
        for pat in patterns:
            if re.search(pat, cleaned, re.IGNORECASE):
                return template_id

    # 보조 키워드로 재시도
    best_id = None
    best_count = 0
    for template_id, keywords in SECONDARY_KEYWORDS.items():
        count = sum(1 for kw in keywords if kw.lower() in cleaned)
        if count > best_count:
            best_count = count
            best_id = template_id

    if best_count >= 1:
        return best_id

    return None


def classify_by_filenames(filenames: list[str]) -> str | None:
    """여러 파일의 이름을 종합해서 가장 가능성 높은 유형 추정."""
    votes = {}
    for f in filenames:
        tid = classify_by_filename(f)
        if tid:
            votes[tid] = votes.get(tid, 0) + 1

    if not votes:
        return None
    # 최다 득표
    return max(votes.items(), key=lambda x: x[1])[0]


def suggest_with_confidence(filename: str) -> tuple[str | None, float]:
    """추정 결과 + 신뢰도 반환.

    Returns:
        (template_id, confidence): confidence ∈ [0.0, 1.0]
    """
    name = Path(filename).stem.lower()
    cleaned = re.sub(r"[\d\-_/\\]+", " ", name)
    cleaned = re.sub(r"\s+", " ", cleaned).strip()

    # 주 키워드 매칭 개수 및 매칭된 패턴 확인
    for template_id, patterns in FILENAME_PATTERNS.items():
        matched_patterns = [pat for pat in patterns
                            if re.search(pat, cleaned, re.IGNORECASE)]

        if matched_patterns:
            # 매칭 개수에 따라 신뢰도 계산
            # 1개 매칭 → 0.75, 2개 → 0.85, 3개+ → 0.95
            conf = min(0.95, 0.65 + 0.1 * len(matched_patterns))
            return template_id, conf

    # 보조 키워드 시도
    for template_id, keywords in SECONDARY_KEYWORDS.items():
        matched = [kw for kw in keywords if kw.lower() in cleaned]
        if matched:
            conf = min(0.6, 0.3 + 0.1 * len(matched))
            return template_id, conf

    return None, 0.0


# ---------------------------------------------------------------------------
# 테스트
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    test_cases = [
        "12995740-M40-001 여수로 수문 설치도(1／2).dxf",
        "12995740-M40-002 여수로 수문 설치도(2／2).dxf",
        "12996710-M40-001 신설 취수탑 설비 설치도(1／2).dxf",
        "12996710-M40-002 신설 취수탑 설비 설치도(2／2).dxf",
        "12996710-M43-002 신설 제수변실 설비 배치도.dxf",
        "1. 좌안옹벽 일반도 작성(2026.0109).dxf",
        "사연댐 전체계획 평면도.dxf",
        "A-Line 교량 상세도.dxf",
        "B-Road 터널 갱구 일반도.dxf",
        "관리사무소 평면도.dxf",
        "P-Station 펌프장 설치도.dxf",
        "random_file.dxf",
    ]

    print("파일명 기반 구조물 유형 추정:")
    print("=" * 70)
    for f in test_cases:
        tid, conf = suggest_with_confidence(f)
        if tid:
            print(f"  [{tid:16}] ({conf:.0%})  {f}")
        else:
            print(f"  [{'─' * 16}] (미매칭)  {f}")
