#!/usr/bin/env python3
"""보고서 요약 추출 공통 모듈.

여러 스크립트에서 공유하는 보고서 파싱 유틸리티.
"""

import re
from pathlib import Path


def extract_report_summary(report_path: Path, max_chars: int = 1000) -> str | None:
    """보고서에서 SCQA의 A(Answer) 또는 첫 섹션 요약 추출.

    추출 우선순위:
    1. ``**A**:``, ``**A.**``, ``**A:**`` 패턴 → 해당 줄부터 다음 ``**`` 또는 ``---``까지
    2. 위 패턴 없으면 첫 번째 ``## `` 섹션 다음의 첫 본문 단락
    3. 둘 다 없으면 파일 첫 10줄

    Args:
        report_path: 보고서 파일 경로
        max_chars: 반환할 최대 문자 수

    Returns:
        추출된 요약 문자열 (max_chars로 truncate).
        파일 없거나 읽기 실패 시 None.
    """
    if not report_path.exists():
        return None

    try:
        content = report_path.read_text(encoding="utf-8")
    except OSError:
        return None

    lines = content.split("\n")

    # 우선순위 1: **A**: / **A.** / **A:** 패턴
    _RE_A_PATTERN = re.compile(r"^\s*\*\*A[.:]?\*\*[.:]?\s*")
    a_start_idx: int | None = None
    for i, line in enumerate(lines):
        if _RE_A_PATTERN.match(line):
            a_start_idx = i
            break

    if a_start_idx is not None:
        # 해당 줄 인라인 텍스트 (패턴 제거 후 나머지)
        first_line = _RE_A_PATTERN.sub("", lines[a_start_idx]).strip()
        collected: list[str] = []
        if first_line:
            collected.append(first_line)

        # 다음 줄부터 ** 또는 --- 가 나오거나 빈 섹션 구분자가 나올 때까지 수집
        for line in lines[a_start_idx + 1 :]:
            if line.startswith("---") or (line.startswith("**") and line.strip().endswith("**")):
                break
            # 새 볼드 키 패턴 (예: **B**: ...) 이 나오면 종료
            if re.match(r"^\s*\*\*[A-Z]\*\*", line):
                break
            collected.append(line)

        result = "\n".join(collected).strip()
        if result:
            return result[:max_chars]

    # 우선순위 2: 첫 번째 ## 섹션 다음의 첫 본문 단락
    first_section_idx: int | None = None
    for i, line in enumerate(lines):
        if line.startswith("## "):
            first_section_idx = i
            break

    if first_section_idx is not None:
        paragraph_lines: list[str] = []
        in_paragraph = False
        for line in lines[first_section_idx + 1 :]:
            # 다음 섹션 헤더 만나면 종료
            if line.startswith("#"):
                if in_paragraph:
                    break
                continue
            if line.strip():
                in_paragraph = True
                paragraph_lines.append(line.strip())
            else:
                if in_paragraph:
                    # 빈 줄 → 단락 종료
                    break

        result = " ".join(paragraph_lines).strip()
        if result:
            return result[:max_chars]

    # 우선순위 3: 파일 첫 10줄
    fallback = "\n".join(lines[:10]).strip()
    if fallback:
        return fallback[:max_chars]

    return None


def extract_report_metadata(report_path: Path) -> dict:
    """보고서에서 테스트 결과, 파일 수, 미해결 이슈를 추출"""
    result: dict = {
        "test_summary": None,
        "files_count": None,
        "unresolved_count": 0,
        "unresolved_items": [],
        "team_id": None,
        "duration": None,
        # 신규 필드
        "title": None,  # str | None
        "issues_resolved": [],  # list[dict] — {"summary": str, "resolution": str}
        "issues_unresolved": [],  # list[dict] — {"summary": str, "resolution": str}
    }

    if not report_path.exists():
        return result

    try:
        content = report_path.read_text(encoding="utf-8")
    except OSError:
        return result

    lines = content.split("\n")

    # --- test_summary ---
    pytest_summary: str | None = None
    pyright_summary: str | None = None
    for line in lines:
        if "pytest" in line.lower() and pytest_summary is None:
            # "N건 전건 통과" 또는 "N건 통과" 패턴
            m = re.search(r"(\d+)건\s*(?:전건\s*)?통과", line)
            if m:
                # "pytest N건 전건 통과" 형태로 출력
                m_full = re.search(r"(\d+건\s*(?:전건\s*)?통과)", line)
                raw = m_full.group(1) if m_full else f"{m.group(1)}건 통과"
                pytest_summary = f"pytest {raw}"
            else:
                # "N/N passed" 패턴
                m2 = re.search(r"(\d+/\d+)\s+passed", line)
                if m2:
                    pytest_summary = f"{m2.group(1)} passed"
        if "pyright" in line.lower() and pyright_summary is None:
            # "0 에러" 패턴
            m = re.search(r"(\d+)\s*에러", line)
            if m:
                pyright_summary = f"pyright {m.group(1)} 에러"
            else:
                # "N errors" 패턴
                m2 = re.search(r"(\d+)\s+errors?", line)
                if m2:
                    pyright_summary = f"pyright {m2.group(1)} errors"

    parts: list[str] = []
    if pytest_summary:
        parts.append(pytest_summary)
    if pyright_summary:
        parts.append(pyright_summary)
    if parts:
        result["test_summary"] = ", ".join(parts)

    # --- files_count ---
    # "생성/수정 파일" 또는 "생성/수정:" 키워드가 있는 ## 섹션에서 bullet(-) 수 카운트
    _RE_FILES_SECTION = re.compile(r"^##\s+.*(?:생성/수정\s*파일|생성/수정:?)")
    in_files_section = False
    bullet_count = 0
    for line in lines:
        if line.startswith("## "):
            if _RE_FILES_SECTION.match(line):
                in_files_section = True
                bullet_count = 0
            else:
                if in_files_section:
                    # 다음 ## 섹션 시작 → 수집 종료
                    break
                in_files_section = False
        elif in_files_section:
            if line.startswith("#"):
                break
            if re.match(r"^\s*-\s+", line):
                bullet_count += 1
    if in_files_section and bullet_count > 0:
        result["files_count"] = bullet_count

    # --- unresolved_count / unresolved_items ---
    _RE_UNRESOLVED_SECTION = re.compile(r"^###+\s+.*범위\s*외\s*미해결")
    in_unresolved = False
    unresolved_items: list[str] = []
    for line in lines:
        if re.match(r"^#+\s+", line):
            if _RE_UNRESOLVED_SECTION.match(line):
                in_unresolved = True
            else:
                if in_unresolved:
                    break
                in_unresolved = False
        elif in_unresolved:
            # "1. **내용**" 형태
            m = re.match(r"^\s*\d+\.\s+\*\*(.+?)\*\*", line)
            if m:
                unresolved_items.append(m.group(1).strip())
    result["unresolved_count"] = len(unresolved_items)
    result["unresolved_items"] = unresolved_items

    # --- team_id ---
    # "(dev2-team" 등의 패턴
    m_team = re.search(r"\((dev\d+-team)\b", content)
    if m_team:
        result["team_id"] = m_team.group(1)
    else:
        # "팀:" / "team:" 패턴
        m_team2 = re.search(r"(?:팀|team)\s*:\s*(\S+)", content, re.IGNORECASE)
        if m_team2:
            result["team_id"] = m_team2.group(1)

    # --- duration ---
    m_dur = re.search(r"소요시간\s*[:\-]?\s*(.+)", content)
    if m_dur:
        result["duration"] = m_dur.group(1).strip()

    # --- title ---
    # 보고서의 첫 번째 "# " 라인 찾기, task-XXX.X 패턴 제거
    for line in lines:
        if line.startswith("# "):
            header_text = line[2:].strip()
            title_text = re.sub(r"^task-\d+\.\d+\s*", "", header_text).strip()
            result["title"] = title_text if title_text else None
            break

    # --- issues_resolved ---
    # "### 자체 해결" 패턴 섹션에서 "1. **이슈 요약** — 해결 방법" 형태 파싱
    _RE_RESOLVED_SECTION = re.compile(r"^###+\s+.*자체\s*해결")
    in_resolved = False
    issues_resolved: list[dict] = []
    for line in lines:
        if re.match(r"^#+\s+", line):
            if _RE_RESOLVED_SECTION.match(line):
                in_resolved = True
            else:
                if in_resolved:
                    break
                in_resolved = False
        elif in_resolved:
            m = re.match(r"^\s*\d+\.\s+\*\*(.+?)\*\*\s*[—\-]+\s*(.+)", line)
            if m:
                issues_resolved.append(
                    {
                        "summary": m.group(1).strip(),
                        "resolution": m.group(2).strip(),
                    }
                )
    result["issues_resolved"] = issues_resolved

    # --- issues_unresolved ---
    # 기존 unresolved_items 로직을 활용하여 구조화된 형태로도 저장
    # "### 범위 외 미해결" 섹션에서 "1. **이슈** — 범위 외 사유: XXX" 파싱
    _RE_UNRESOLVED_STRUCT_SECTION = re.compile(r"^###+\s+.*범위\s*외\s*미해결")
    in_unresolved_struct = False
    issues_unresolved: list[dict] = []
    for line in lines:
        if re.match(r"^#+\s+", line):
            if _RE_UNRESOLVED_STRUCT_SECTION.match(line):
                in_unresolved_struct = True
            else:
                if in_unresolved_struct:
                    break
                in_unresolved_struct = False
        elif in_unresolved_struct:
            m = re.match(r"^\s*\d+\.\s+\*\*(.+?)\*\*\s*[—\-]+\s*(.+)", line)
            if m:
                issues_unresolved.append(
                    {
                        "summary": m.group(1).strip(),
                        "resolution": m.group(2).strip(),
                    }
                )
    result["issues_unresolved"] = issues_unresolved

    return result


def format_notification_message(task_id: str, report_path: Path, done_data: dict | None = None) -> str:
    """완료 알림 메시지를 마크다운 포맷으로 생성"""
    MAX_LEN = 4096

    summary = extract_report_summary(report_path, max_chars=800)
    meta = extract_report_metadata(report_path)

    team_id: str | None = meta.get("team_id")
    duration: str | None = meta.get("duration")
    title: str | None = meta.get("title")

    if done_data:
        if done_data.get("team_id"):
            team_id = str(done_data["team_id"])
        if done_data.get("duration_seconds") is not None:
            secs = int(done_data["duration_seconds"])
            minutes = secs // 60
            seconds = secs % 60
            duration = f"{minutes}분 {seconds}초"

    # 1) 볼드 헤더 (team_id 포함)
    if team_id:
        msg_lines: list[str] = [f"**{task_id} 완료 보고** ({team_id})"]
    else:
        msg_lines = [f"**{task_id} 완료 보고**"]

    # 2) 제목 + 소요시간
    title_parts: list[str] = []
    if title:
        title_parts.append(f"**{title}**")
    if duration:
        if title_parts:
            title_parts.append(f"({duration})")
        else:
            title_parts.append(duration)
    if title_parts:
        msg_lines.append(" ".join(title_parts))

    # 3) 핵심 결과
    if summary:
        msg_lines.append("")
        msg_lines.append("**핵심 결과**")
        msg_lines.append(summary)

    # 4) 파일 정보 (이모지 대신 텍스트)
    files_count = meta.get("files_count")
    test_summary = meta.get("test_summary")
    info_parts: list[str] = []
    if files_count is not None:
        info_parts.append(f"생성/수정: {files_count}개 파일")
    if test_summary:
        info_parts.append(f"테스트: {test_summary}")
    if info_parts:
        msg_lines.append(", ".join(info_parts))

    # 5) 발견/해결 이슈
    issues_resolved: list[dict] = meta.get("issues_resolved", [])
    issues_unresolved_structured: list[dict] = meta.get("issues_unresolved", [])
    unresolved_items: list[str] = meta.get("unresolved_items", [])

    total_issues = len(issues_resolved) + max(len(issues_unresolved_structured), meta.get("unresolved_count", 0))

    if total_issues > 0:
        msg_lines.append("")
        msg_lines.append(f"**발견/해결 이슈 {total_issues}건**")
        num = 1
        for item in issues_resolved:
            msg_lines.append(f"{num}. **{item['summary']}** — {item['resolution']}")
            num += 1
        for item in issues_unresolved_structured:
            msg_lines.append(f"{num}. **{item['summary']}** — 미해결: {item['resolution']}")
            num += 1
        if not issues_unresolved_structured and unresolved_items:
            for item_text in unresolved_items:
                msg_lines.append(f"{num}. **{item_text}** — 미해결")
                num += 1

    message = "\n".join(msg_lines)

    # Telegram 4096자 제한
    if len(message) > MAX_LEN:
        message = message[:MAX_LEN]

    return message
