# -*- coding: utf-8 -*-
"""프로젝트 귀속: 표제란 PROJECT > 파일명 > 폴더명 순 추정 + 별칭 사전.

부서마다 다른 프로젝트 이름("삼성3차", "2024-15")을 강제 통일하지 않고
aliases.yaml로 정규 번호로 '번역'한다 (DECISIONS 2026-08-20).
"""

from __future__ import annotations

import re
from pathlib import PurePosixPath

import yaml

from watcher.extract.base import Document

# 프로젝트 번호 관례 패턴 (별칭 사전에 없어도 이 꼴이면 그 자체를 정규 번호로 본다)
# \b는 '_' 앞뒤에서 매칭되지 않아 파일명(P25-007_발주서)에서 놓친다 → lookaround 사용
PROJECT_NO_RE = re.compile(r"(?<![A-Z0-9])[A-Z]\d{2}-\d{3}(?!\d)")

UNASSIGNED = "미분류"


class ProjectResolver:
    def __init__(self, aliases: dict[str, list[str]] | None = None,
                 root_labels: tuple | list = ()):
        # canonical -> [alias...]. 역방향 조회용 사전을 만든다 (대소문자 무시)
        self.aliases = aliases or {}
        # 다중 감시 폴더의 라벨(경로 첫 조각) — 폴더 구조 귀속에서 건너뛴다
        self.root_labels = set(root_labels)
        self._lookup: dict[str, str] = {}
        for canonical, names in self.aliases.items():
            self._lookup[canonical.upper()] = canonical
            for n in names:
                self._lookup[str(n).upper()] = canonical

    @classmethod
    def load(cls, path) -> "ProjectResolver":
        try:
            with open(path, "rb") as f:
                data = yaml.safe_load(f) or {}
        except FileNotFoundError:
            data = {}
        return cls({str(k): list(v or []) for k, v in data.items()})

    def canonical(self, name: str) -> str | None:
        """정확히 일치하는 정규 번호/별칭 → 정규 번호. 패턴 일치면 그 자체."""
        hit = self._lookup.get(name.strip().upper())
        if hit:
            return hit
        m = PROJECT_NO_RE.search(name)
        return m.group() if m else None

    def _find_in(self, text: str) -> str | None:
        """문자열 안에서 정규 번호·별칭·패턴을 찾는다 (부분 문자열)."""
        up = text.upper()
        for key, canonical in self._lookup.items():
            if key in up:
                return canonical
        m = PROJECT_NO_RE.search(text)
        return m.group() if m else None

    def attribute(self, rel_path: str, doc: Document | None) -> tuple[str, str]:
        """(프로젝트, 근거 출처). 출처: 표제란 > 파일명 > 폴더명(별칭) > 폴더 구조 > 미분류."""
        if doc is not None and doc.project:
            return self.canonical(doc.project) or doc.project, "표제란"
        p = PurePosixPath(rel_path)
        hit = self._find_in(p.name)
        if hit:
            return hit, "파일명"
        for folder in reversed(p.parent.parts):
            hit = self._find_in(folder)
            if hit:
                return hit, "폴더명"
        # 폴더 구조 규칙: 감시 폴더 바로 아래 첫 폴더 = 프로젝트
        # (예: 지정폴더\SKH M15\세부PJT\도면\... → 프로젝트 "SKH M15")
        folders = list(p.parent.parts)
        if folders and folders[0] in self.root_labels:
            folders = folders[1:]
        if folders:
            return folders[0], "폴더 구조"
        return UNASSIGNED, "미분류"
