# -*- coding: utf-8 -*-
"""
Content Analyzer (Phase 3 — Layer A)
- template_info + semantic_map → content_prompt.json
- 각 placeholder의 의미/유형/예시값/작성 패턴 추출
- Phase 5에서 AI가 새 문서 생성 시 "레시피"로 참조

★ 원칙: 모든 분류는 코드 100% (AI 없음)
   purpose_hint / audience_hint / tone_hint는 빈 문자열로 남김
   → 추후 AI enrichment 단계에서 채울 수 있도록 설계
"""

import re


def generate(template_info: dict, semantic_map: dict,
             parsed: dict = None) -> dict:
    """
    content_prompt.json 생성

    Args:
        template_info: doc_template_analyzer 추출 결과
        semantic_map: semantic_mapper 분류 결과
        parsed: HWPX 파싱 원본 (선택)

    Returns:
        content_prompt.json 구조
    """
    placeholders = {}
    table_guide = {}

    # ① 문서 기본 정보
    document = _analyze_document(template_info)

    # ② 헤더 placeholders
    _analyze_header(template_info, placeholders)

    # ③ 푸터 placeholders
    _analyze_footer(template_info, placeholders)

    # ④ 제목 placeholder
    _analyze_title(template_info, semantic_map, placeholders)

    # ⑤ 섹션 placeholders
    _analyze_sections(semantic_map, placeholders, template_info)

    # ⑤-b content_order 기반 문단/이미지 placeholders
    _analyze_content_order(template_info, semantic_map, placeholders)

    # ⑥ 표 가이드 + placeholders
    _analyze_tables(template_info, semantic_map,
                    placeholders, table_guide)

    # ⑦ 작성 패턴
    writing_guide = _analyze_writing_patterns(template_info, semantic_map)

    return {
        "version": "1.0",
        "document": document,
        "placeholders": placeholders,
        "table_guide": table_guide,
        "writing_guide": writing_guide
    }


# ================================================================
#  문서 기본 정보
# ================================================================

def _analyze_document(template_info: dict) -> dict:
    """문서 레벨 정보 추출"""
    page = template_info.get("page", {})
    paper = page.get("paper", {})

    return {
        "paper": paper.get("name", "A4"),
        "layout": "landscape" if paper.get("landscape") else "portrait",
        "margins": page.get("margins", {}),
        "purpose_hint": "",    # AI enrichment 예약
        "audience_hint": "",   # AI enrichment 예약
        "tone_hint": ""        # AI enrichment 예약
    }


# ================================================================
#  텍스트 유형 분류 (코드 100%, AI 없음)
# ================================================================

def _classify_text(text: str) -> dict:
    """텍스트 패턴으로 콘텐츠 유형 분류"""
    text = text.strip()
    if not text:
        return {"type": "empty", "pattern": "빈 셀"}

    # 날짜: "2025. 1. 30(금)", "2025-01-30", "2025.01.30"
    if re.match(r'\d{4}[\.\-/]\s*\d{1,2}[\.\-/]\s*\d{1,2}', text):
        return {"type": "date", "pattern": "날짜 (YYYY. M. D)"}

    # ★ 직급+이름 (부서보다 먼저!)
    positions = [
        '사원', '대리', '과장', '차장', '부장', '이사', '상무', '전무',
        '연구원', '선임연구원', '책임연구원', '수석연구원',
        '주임', '계장', '팀장', '실장', '부서장', '센터장'
    ]
    for pos in positions:
        if pos in text:
            return {"type": "author", "pattern": f"이름 + 직급({pos})"}

    # 부서 (직급 아닌 것만 여기로)
    if re.search(r'(실|부|국|과|원|처|센터|본부)$', text) and len(text) <= 12:
        return {"type": "department", "pattern": "조직명"}

    # 팀
    if re.search(r'팀$', text) and len(text) <= 10:
        return {"type": "team", "pattern": "팀명"}

    # 페이지 참조: "1p", "2p"
    if re.match(r'\d+p$', text):
        return {"type": "page_ref", "pattern": "페이지 참조"}

    # 문서 제목: ~계획(안), ~보고서, ~제안서 등
    if re.search(r'(계획|보고서|제안서|기획서|결과|방안|현황|분석)'
                 r'\s*(\(안\))?\s*$', text):
        return {"type": "doc_title", "pattern": "문서 제목"}

    # 슬로건/비전 (길고 추상적 키워드 포함)
    if len(text) > 10 and any(k in text for k in
                              ['함께', '세상', '미래', '가치', '만들어']):
        return {"type": "slogan", "pattern": "회사 슬로건/비전"}

    # 기본
    return {"type": "text", "pattern": "자유 텍스트"}


# ================================================================
#  헤더 분석
# ================================================================

def _analyze_header(template_info: dict, placeholders: dict):
    """헤더 영역 placeholder 분석"""
    header = template_info.get("header", {})
    if not header or not header.get("exists"):
        return

    if header.get("type") == "table" and header.get("table"):
        _analyze_table_area(header["table"], "HEADER", "header",
                            placeholders)
    else:
        texts = header.get("texts", [])
        for i in range(max(len(texts), 1)):
            ph = f"HEADER_TEXT_{i+1}"
            example = texts[i] if i < len(texts) else ""
            info = _classify_text(example)
            info["example"] = example.strip()
            info["location"] = "header"
            placeholders[ph] = info


# ================================================================
#  푸터 분석
# ================================================================

def _analyze_footer(template_info: dict, placeholders: dict):
    """푸터 영역 placeholder 분석"""
    footer = template_info.get("footer", {})
    if not footer or not footer.get("exists"):
        return

    if footer.get("type") == "table" and footer.get("table"):
        _analyze_table_area(footer["table"], "FOOTER", "footer",
                            placeholders)
    else:
        placeholders["PAGE_NUMBER"] = {
            "type": "page_number",
            "pattern": "페이지 번호",
            "example": "1",
            "location": "footer"
        }


# ================================================================
#  헤더/푸터 공통: 표 형태 영역 분석
# ================================================================

def _analyze_table_area(tbl: dict, prefix: str, location: str,
                        placeholders: dict):
    """표 형태의 헤더/푸터 → placeholder 매핑

    Args:
        tbl: header["table"] 또는 footer["table"]
        prefix: "HEADER" 또는 "FOOTER"
        location: "header" 또는 "footer"
        placeholders: 결과 dict (in-place 수정)
    """
    rows = tbl.get("rows", [])

    for r_idx, row in enumerate(rows):
        for c_idx, cell in enumerate(row):
            lines = cell.get("lines", [])

            if len(lines) > 1:
                for l_idx, line_text in enumerate(lines):
                    ph = f"{prefix}_R{r_idx+1}_C{c_idx+1}_LINE_{l_idx+1}"
                    info = _classify_text(line_text)
                    info["example"] = line_text.strip()
                    info["location"] = location
                    placeholders[ph] = info
            elif lines:
                ph = f"{prefix}_R{r_idx+1}_C{c_idx+1}"
                info = _classify_text(lines[0])
                info["example"] = lines[0].strip()
                info["location"] = location
                placeholders[ph] = info
            else:
                ph = f"{prefix}_R{r_idx+1}_C{c_idx+1}"
                placeholders[ph] = {
                    "type": "empty",
                    "pattern": "빈 셀 (로고/여백)",
                    "example": "",
                    "location": location
                }


# ================================================================
#  제목 분석
# ================================================================

def _analyze_title(template_info: dict, semantic_map: dict,
                   placeholders: dict):
    """제목 블록 placeholder 분석

    ★ v1.1: template_manager._build_title_block_html()과 동일한
       TITLE_R{r}_C{c} 명명 규칙 사용 (범용 매핑)
    """
    title_idx = semantic_map.get("title_table")
    if title_idx is None:
        return

    tables = template_info.get("tables", [])
    title_tbl = next((t for t in tables if t["index"] == title_idx), None)
    if not title_tbl:
        return

    # 각 셀별로 placeholder 생성 (template과 동일한 이름)
    for r_idx, row in enumerate(title_tbl.get("rows", [])):
        for c_idx, cell in enumerate(row):
            cell_text = cell.get("text", "").strip()
            if not cell_text:
                continue  # 빈 셀은 template에서도 placeholder 없음

            ph_name = f"TITLE_R{r_idx+1}_C{c_idx+1}"
            info = _classify_text(cell_text)
            if "title" not in info["type"] and "doc_title" not in info["type"]:
                # 제목표 안의 텍스트가 doc_title이 아닐 수도 있음 (부제 등)
                # 가장 긴 텍스트만 doc_title로 분류
                pass
            info["example"] = cell_text
            info["location"] = "title_block"
            placeholders[ph_name] = info

    # 가장 긴 텍스트를 가진 셀을 doc_title로 마킹
    longest_ph = None
    longest_len = 0
    for ph_key in list(placeholders.keys()):
        if ph_key.startswith("TITLE_R"):
            ex = placeholders[ph_key].get("example", "")
            if len(ex) > longest_len:
                longest_len = len(ex)
                longest_ph = ph_key
    if longest_ph:
        placeholders[longest_ph]["type"] = "doc_title"
        placeholders[longest_ph]["pattern"] = "문서 제목"


# ================================================================
#  섹션 분석
# ================================================================

def _analyze_sections(semantic_map: dict, placeholders: dict,
                      template_info: dict = None):
    """섹션 placeholder 분석.

    content_order에 문단이 있으면 SECTION_n_CONTENT는 생략
    (개별 PARA_n이 본문 역할을 대신함).
    """
    sections = semantic_map.get("sections", [])

    # content_order에 문단이 있으면 개별 PARA_n이 본문 담당 → CONTENT 불필요
    has_co_paragraphs = False
    if template_info:
        co = template_info.get("content_order", [])
        has_co_paragraphs = any(c['type'] == 'paragraph' for c in co) if co else False

    if not sections:
        placeholders["SECTION_1_TITLE"] = {
            "type": "section_title", "pattern": "섹션 제목",
            "example": "", "location": "body"
        }
        if not has_co_paragraphs:
            placeholders["SECTION_1_CONTENT"] = {
                "type": "section_content", "pattern": "섹션 본문",
                "example": "", "location": "body"
            }
        return

    for i, sec in enumerate(sections):
        s_num = i + 1
        title_text = sec if isinstance(sec, str) else sec.get("title", "")

        placeholders[f"SECTION_{s_num}_TITLE"] = {
            "type": "section_title", "pattern": "섹션 제목",
            "example": title_text, "location": "body"
        }
        if not has_co_paragraphs:
            placeholders[f"SECTION_{s_num}_CONTENT"] = {
                "type": "section_content", "pattern": "섹션 본문",
                "example": "", "location": "body"
            }

# ================================================================
#  content_order 기반 문단/이미지 분석 (v5.2+)
# ================================================================

def _analyze_content_order(template_info: dict, semantic_map: dict,
                           placeholders: dict):
    """content_order의 paragraph/image → PARA_n, IMAGE_n placeholder 생성.

    content_order가 없거나 문단이 없으면 아무것도 안 함 (legacy 호환).
    """
    content_order = template_info.get("content_order")
    if not content_order:
        return
    if not any(c['type'] == 'paragraph' for c in content_order):
        return

    # 섹션 제목 패턴 (template_manager와 동일)
    sec_patterns = [
        re.compile(r'^\d+\.\s+\S'),
        re.compile(r'^[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ]\.\s*\S'),
        re.compile(r'^제\s*\d+\s*[장절항]\s*\S'),
    ]

    para_num = 0
    img_num = 0
    section_num = 0

    for item in content_order:
        itype = item['type']

        if itype == 'empty':
            continue

        # ── 표: _analyze_tables에서 처리 → 건너뛰기 ──
        if itype == 'table':
            continue

        # ── 이미지 ──
        if itype == 'image':
            img_num += 1
            placeholders[f"IMAGE_{img_num}"] = {
                "type": "image",
                "pattern": "이미지",
                "example_ref": item.get("binaryItemIDRef", ""),
                "location": "body"
            }
            caption = item.get("text", "")
            if caption:
                placeholders[f"IMAGE_{img_num}_CAPTION"] = {
                    "type": "image_caption",
                    "pattern": "이미지 캡션",
                    "example": caption,
                    "location": "body"
                }
            continue

        # ── 문단 ──
        if itype == 'paragraph':
            text = item.get('text', '')

            # 섹션 제목 → SECTION_n_TITLE (이미 _analyze_sections에서 등록됐을 수 있음)
            if any(p.match(text) for p in sec_patterns):
                section_num += 1
                ph = f"SECTION_{section_num}_TITLE"
                if ph not in placeholders:
                    placeholders[ph] = {
                        "type": "section_title",
                        "pattern": "섹션 제목",
                        "example": text,
                        "location": "body"
                    }
                continue

            # 일반 문단
            para_num += 1
            runs = item.get('runs', [])

            if len(runs) > 1:
                # 다중 run → 각 run별 placeholder
                for r_idx, run in enumerate(runs):
                    ph = f"PARA_{para_num}_RUN_{r_idx+1}"
                    run_text = run.get("text", "")
                    info = _classify_text(run_text)
                    info["example"] = run_text[:100] if len(run_text) > 100 else run_text
                    info["location"] = "body"
                    info["run_index"] = r_idx + 1
                    placeholders[ph] = info
            else:
                ph = f"PARA_{para_num}"
                info = _classify_text(text)
                info["example"] = text[:100] if len(text) > 100 else text
                info["location"] = "body"
                placeholders[ph] = info


# ================================================================
#  표 분석 → placeholder + 표 가이드
# ================================================================

def _analyze_tables(template_info: dict, semantic_map: dict,
                    placeholders: dict, table_guide: dict):
    """본문 데이터 표 → placeholder + table_guide"""
    tables = template_info.get("tables", [])
    body_indices = semantic_map.get("body_tables", [])
    table_roles = semantic_map.get("table_roles", {})

    for tbl_num_0, tbl_idx in enumerate(body_indices):
        tbl_num = tbl_num_0 + 1
        tbl = next((t for t in tables if t["index"] == tbl_idx), None)
        if not tbl:
            continue

        role_info = table_roles.get(tbl_idx, table_roles.get(str(tbl_idx), {}))
        col_headers = role_info.get("col_headers", [])
        col_cnt = len(col_headers) if col_headers else tbl.get("colCnt", 0)

        # ── 헤더 placeholder ──
        for c_idx, h_text in enumerate(col_headers):
            ph = f"TABLE_{tbl_num}_H_C{c_idx+1}"
            placeholders[ph] = {
                "type": "table_header", "pattern": "표 열 제목",
                "example": h_text, "location": f"table_{tbl_num}"
            }

        # ── BODY placeholder ──
        placeholders[f"TABLE_{tbl_num}_BODY"] = {
            "type": "table_body",
            "pattern": "표 데이터 행들 (HTML <tr> 반복)",
            "example": "",
            "location": f"table_{tbl_num}"
        }

        # ── 표 가이드 ──
        table_guide[str(tbl_num)] = {
            "col_headers": col_headers,
            "col_count": col_cnt,
            "row_count": tbl.get("rowCnt", 0),
            "merge_pattern": _detect_merge_pattern(tbl),
            "bullet_chars": _detect_bullet_chars(tbl),
            "example_rows": _extract_example_rows(tbl, role_info),
            "col_types": _classify_columns(col_headers),
            "row_bf_pattern": _extract_row_bf_pattern(tbl, role_info),           
        }


def _detect_merge_pattern(tbl: dict) -> dict:
    """셀 병합 패턴 감지"""
    pattern = {}
    for row in tbl.get("rows", []):
        for cell in row:
            col = cell.get("colAddr", 0)
            if cell.get("rowSpan", 1) > 1:
                pattern.setdefault(f"col_{col}", "row_group")
            if cell.get("colSpan", 1) > 1:
                pattern.setdefault(f"col_{col}", "col_span")
    return pattern


def _detect_bullet_chars(tbl: dict) -> list:
    """표 셀 텍스트에서 불릿 문자 감지"""
    bullets = set()
    pats = [
        (r'^-\s',  '- '),  (r'^·\s',  '· '),  (r'^•\s',  '• '),
        (r'^▸\s',  '▸ '),  (r'^▶\s',  '▶ '),  (r'^※\s',  '※ '),
        (r'^◈\s',  '◈ '),  (r'^○\s',  '○ '),  (r'^●\s',  '● '),
    ]
    for row in tbl.get("rows", []):
        for cell in row:
            for line in cell.get("lines", []):
                for pat, char in pats:
                    if re.match(pat, line.strip()):
                        bullets.add(char)
    return sorted(bullets)


def _extract_example_rows(tbl: dict, role_info: dict) -> list:
    """데이터 행에서 예시 최대 3행 추출"""
    rows = tbl.get("rows", [])
    header_row = role_info.get("header_row")
    if header_row is None:
        header_row = -1

    examples = []
    for r_idx, row in enumerate(rows):
        if r_idx <= header_row:
            continue
        row_data = []
        for cell in row:
            text = cell.get("text", "").strip()
            if len(text) > 80:
                text = text[:77] + "..."
            row_data.append(text)
        examples.append(row_data)
        if len(examples) >= 3:
            break
    return examples


def _classify_columns(col_headers: list) -> list:
    """열 헤더 키워드로 용도 추론"""
    type_map = {
        "category": ['구분', '분류', '항목', '카테고리'],
        "content":  ['내용', '설명', '상세', '세부내용'],
        "note":     ['비고', '참고', '기타', '메모'],
        "date":     ['날짜', '일자', '일시', '기간'],
        "person":   ['담당', '담당자', '작성자', '책임'],
        "number":   ['수량', '금액', '단가', '합계'],
    }
    result = []
    for c_idx, header in enumerate(col_headers):
        h = header.strip()
        col_type = "text"
        for t, keywords in type_map.items():
            if h in keywords:
                col_type = t
                break
        result.append({"col": c_idx, "type": col_type, "header": h})
    return result

def _extract_row_bf_pattern(tbl: dict, role_info: dict) -> list:
    """첫 데이터행의 셀별 borderFillIDRef → 열별 bf class 패턴.

    AI가 TABLE_BODY <td> 생성 시 class="bf-{id}" 적용하도록 안내.
    예: [{"col": 0, "bf_class": "bf-12"}, {"col": 1, "bf_class": "bf-8"}, ...]
    """
    rows = tbl.get("rows", [])
    header_row = role_info.get("header_row")
    if header_row is None:
        header_row = -1

    # 첫 데이터행 찾기
    for r_idx, row in enumerate(rows):
        if r_idx <= header_row:
            continue
        pattern = []
        for cell in row:
            bf_id = cell.get("borderFillIDRef")
            pattern.append({
                "col": cell.get("colAddr", len(pattern)),
                "bf_class": f"bf-{bf_id}" if bf_id else "",
                "colSpan": cell.get("colSpan", 1),
                "rowSpan": cell.get("rowSpan", 1),
            })
        return pattern

    return []
# ================================================================
#  작성 패턴 분석
# ================================================================

def _analyze_writing_patterns(template_info: dict,
                              semantic_map: dict) -> dict:
    """문서 전체의 작성 패턴 분석"""
    result = {
        "bullet_styles": [],
        "numbering_patterns": [],
        "avg_line_length": 0,
        "font_primary": "",
        "font_size_body": ""
    }

    # ── 불릿 수집 (모든 표 텍스트) ──
    all_bullets = set()
    tables = template_info.get("tables", [])
    for tbl in tables:
        for row in tbl.get("rows", []):
            for cell in row:
                for line in cell.get("lines", []):
                    if re.match(r'^[-·•▸▶※◈○●]\s', line.strip()):
                        all_bullets.add(line.strip()[0] + " ")

    # ── numbering tools 데이터 ──
    numbering = template_info.get("numbering", {})
    for num in numbering.get("numberings", []):
        levels = num.get("levels", [])
        patterns = [lv.get("pattern", "") for lv in levels[:3]]
        if patterns:
            result["numbering_patterns"].append(patterns)

    for b in numbering.get("bullets", []):
        char = b.get("char", "")
        if char:
            all_bullets.add(char + " ")

    result["bullet_styles"] = sorted(all_bullets)

# ── 평균 라인 길이 ──
    lengths = []
    for tbl in tables:
        for row in tbl.get("rows", []):
            for cell in row:
                for line in cell.get("lines", []):
                    if line.strip():
                        lengths.append(len(line.strip()))

    # content_order 문단 텍스트도 포함
    content_order = template_info.get("content_order", [])
    for item in content_order:
        if item['type'] == 'paragraph':
            text = item.get('text', '').strip()
            if text:
                lengths.append(len(text))
                # 불릿 감지도 추가
                if re.match(r'^[-·•▸▶※◈○●]\s', text):
                    all_bullets.add(text[0] + " ")

    if lengths:
        result["avg_line_length"] = round(sum(lengths) / len(lengths))

    # ── 주요 폰트 ──
    fonts = template_info.get("fonts", {})
    hangul = fonts.get("HANGUL", [])
    if hangul and isinstance(hangul, list) and len(hangul) > 0:
        result["font_primary"] = hangul[0].get("face", "")

    # ── 본문 글자 크기 (char_styles id=0 기본) ──
    char_styles = template_info.get("char_styles", [])
    if char_styles:
        result["font_size_body"] = f"{char_styles[0].get('height_pt', 10)}pt"

    return result