# -*- coding: utf-8 -*-
"""Step 1: 기등재 혼성어 목록에서 N-Gram 패턴 추출

입력: resource/wordlist.xlsx
출력: output/{corpus_type}/step1_patterns.csv
"""

from __future__ import annotations

from collections import defaultdict
from statistics import mean, stdev

import pandas as pd
from tqdm.auto import tqdm

from wordextractor.config import PipelineConfig
from wordextractor.utils.korean import keep_korean


def choose_n(
    syllable_len: int,
    *,
    ngram_rules: dict[int, int],
    ngram_default: int,
    min_syllable: int,
) -> int | None:
    if syllable_len < min_syllable:
        return None
    return ngram_rules.get(syllable_len, ngram_default)


def extract_patterns(
    words: pd.Series,
    *,
    ngram_rules: dict[int, int],
    ngram_default: int,
    min_syllable: int,
) -> pd.DataFrame:
    positions: dict[str, list[float]] = defaultdict(list)
    sources: dict[str, set[str]] = defaultdict(set)

    for headword in tqdm(words, desc="n-gram 패턴 추출"):
        clean = keep_korean(headword)
        if not clean:
            continue
        n = choose_n(
            len(clean),
            ngram_rules=ngram_rules,
            ngram_default=ngram_default,
            min_syllable=min_syllable,
        )
        if n is None or len(clean) < n:
            continue

        span = len(clean) - n
        for i in range(span + 1):
            pat = clean[i : i + n]
            positions[pat].append(i / span if span > 0 else 0.0)
            sources[pat].add(clean)

    rows = []
    for pat in positions:
        src_set = sources[pat]
        freq = len(src_set)
        pos_list = positions[pat]
        avg_pos = mean(pos_list)
        std_pos = stdev(pos_list) if len(pos_list) >= 2 else 0.0
        src = "; ".join(sorted(src_set))
        rows.append((pat, len(pat), freq, round(avg_pos, 4), round(std_pos, 4), src))

    return (
        pd.DataFrame(
            rows,
            columns=["패턴", "패턴 길이", "빈도", "패턴 위칫값 평균", "패턴 위칫값의 표준편차", "혼성어 목록"],
        )
        .sort_values(["패턴 길이", "빈도"], ascending=[True, False])
        .reset_index(drop=True)
    )


def run(cfg: PipelineConfig) -> None:
    out_dir = cfg.ensure_output_dir()

    print("혼성어 DB 로드...")
    words_df = pd.read_excel(cfg.wordlist_path)
    print(f"  전체: {len(words_df)}개")

    words_df = words_df[words_df[cfg.syllable_column] >= cfg.min_syllable]
    print(f"  {cfg.min_syllable}음절 이상: {len(words_df)}개")

    texts = words_df[cfg.blend_column].dropna().astype(str)

    print("\n패턴 추출 중...")
    all_patterns = extract_patterns(
        texts,
        ngram_rules=cfg.ngram_rules,
        ngram_default=cfg.ngram_default,
        min_syllable=cfg.min_syllable,
    )
    print(f"  전체 패턴 수: {len(all_patterns):,}개")

    all_path = out_dir / "step1_patterns_all.csv"
    all_patterns.to_csv(all_path, index=False, encoding="utf-8-sig")
    print(f"\n전체 패턴 저장: {all_path}")

    filtered = all_patterns[
        (all_patterns["빈도"] >= cfg.min_pattern_freq) & (all_patterns["패턴 위칫값 평균"] == 1.0)
    ].reset_index(drop=True)
    print(f"  빈도 {cfg.min_pattern_freq}+ & 위칫값 평균==1: {len(filtered):,}개")

    filtered_path = out_dir / "step1_patterns.csv"
    filtered.to_csv(filtered_path, index=False, encoding="utf-8-sig")
    print(f"필터링 패턴 저장: {filtered_path}")

    print(f"\n=== 요약 ===")
    print(f"  전체 패턴: {len(all_patterns):,}개")
    print(f"  필터링 패턴: {len(filtered):,}개")
