# -*- coding: utf-8 -*-
"""정리 제안 (읽기 전용). 파일을 옮기지 않는다 — '옮기면 좋아 보인다'고 표시만 한다.

원칙 2(읽기 전용) 유지: 이 모듈은 어떤 파일도 이동·수정·삭제하지 않는다.
제안의 근거는 프로젝트 귀속 결과다 — 표제란/파일명으로 확정된 프로젝트와
파일이 실제 놓인 폴더가 어긋날 때만 제안한다(원칙 4: 근거 있는 것만).
"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import PurePosixPath


@dataclass(frozen=True)
class Suggestion:
    path: str            # 현재 경로 (라벨/상대경로)
    project: str         # 귀속된 프로젝트
    how: str             # 귀속 근거 (표제란/파일명)
    current_folder: str  # 지금 들어있는 폴더
    reason: str          # 사람이 읽을 제안 사유


# 폴더명으로 귀속됐거나 미분류인 건 제안하지 않는다 — 확신이 약하면 침묵한다.
_CONFIDENT = {"표제란", "파일명"}


def suggest_moves(attributions: dict, folder_project=None) -> list[Suggestion]:
    """attributions: {경로: (project, how)} → 정리 제안 목록.

    제안 조건(소음 방지): 파일이 표제란·파일명으로 '확실히' 프로젝트 X인데,
    그 파일이 든 폴더가 '다른 프로젝트 Y'를 가리킬 때만 제안한다 — 즉 명백한
    오배치. folder_project(폴더경로 -> 프로젝트|None)로 별칭까지 해석하므로,
    '전장도면'처럼 별칭으로 X와 같은 폴더는 제안하지 않는다.
    folder_project가 없으면 프로젝트 번호 문자열 포함 여부로 보수적으로 판단.
    """
    out: list[Suggestion] = []
    for path, (project, how) in sorted(attributions.items()):
        if how not in _CONFIDENT or not project:
            continue
        parent = str(PurePosixPath(path).parent)
        if folder_project is not None:
            fp = folder_project(parent)
            # 폴더가 무프로젝트이거나 같은 프로젝트면 제자리 — 다른 프로젝트일 때만 제안
            if fp is None or fp == project:
                continue
            reason = (f"{how} 기준 이 파일의 프로젝트는 {project}인데, 폴더 '{parent}'는 "
                      f"{fp} 프로젝트로 보입니다. 폴더가 뒤바뀌었는지 확인하세요.")
        else:
            if project.upper() in parent.upper():
                continue
            reason = (f"{how} 기준 프로젝트는 {project}인데 '{parent}' 폴더에 있습니다.")
        out.append(Suggestion(path=path, project=project, how=how,
                              current_folder=parent, reason=reason))
    return out
