//! Identify phrases with more than one pinyin reading variant.
//!
//! Scans `data/phrases_composed.tsv`, groups by phrase, counts distinct
//! pinyin strings per phrase, retains those with >1, sorts by jieba freq
//! desc, writes the top N to `data/heteronyms_candidates.tsv` as an
//! analysis artifact.
//!
//! Output is gitignored — it's a derivative of phrases_composed.tsv that
//! anyone can regenerate. The actual curation product lives in
//! `data/heteronyms_curated.tsv` (committed, hand-edited).
//!
//! Run via:
//!     cargo run --features tools --bin find-heteronym-candidates --release

use std::collections::HashMap;
use std::collections::HashSet;
use std::env;
use std::fs;
use std::io::{BufWriter, Write};
use std::path::PathBuf;

const TOP_N: usize = 1500;

fn main() -> std::io::Result<()> {
    let crate_dir =
        PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()));
    let src = crate_dir.join("data/phrases_composed.tsv");
    let dst = crate_dir.join("data/heteronyms_candidates.tsv");

    let txt = fs::read_to_string(&src).unwrap_or_else(|_| {
        panic!(
            "{} missing — run tools/compose-phrase-readings first (item 15)",
            src.display()
        )
    });

    // phrase → (set of distinct pinyins, max jieba freq seen)
    let mut by_phrase: HashMap<String, (HashSet<String>, u64)> = HashMap::with_capacity(400_000);
    let mut total_rows = 0u64;

    for line in txt.lines() {
        if line.is_empty() || line.starts_with('#') {
            continue;
        }
        total_rows += 1;
        let mut parts = line.split('\t');
        let pinyin = parts.next().unwrap_or("");
        let phrase = parts.next().unwrap_or("");
        let freq: u64 = parts
            .next()
            .and_then(|s| s.trim().parse().ok())
            .unwrap_or(0);
        if pinyin.is_empty() || phrase.is_empty() {
            continue;
        }
        let entry = by_phrase
            .entry(phrase.to_string())
            .or_insert_with(|| (HashSet::new(), 0));
        entry.0.insert(pinyin.to_string());
        if freq > entry.1 {
            entry.1 = freq;
        }
    }

    // Filter > 1 reading, sort by freq desc.
    let mut results: Vec<(String, Vec<String>, u64)> = by_phrase
        .into_iter()
        .filter(|(_, (pys, _))| pys.len() > 1)
        .map(|(ph, (pys, f))| {
            let mut v: Vec<String> = pys.into_iter().collect();
            v.sort();
            (ph, v, f)
        })
        .collect();
    results.sort_by(|a, b| b.2.cmp(&a.2).then_with(|| a.0.cmp(&b.0)));

    let take = results.len().min(TOP_N);
    let mut w = BufWriter::new(fs::File::create(&dst)?);
    writeln!(
        w,
        "# heteronyms_candidates.tsv — generated by find_heteronym_candidates"
    )?;
    writeln!(w, "# format: <phrase>\\t<freq>\\t<pinyin1>[,<pinyin2>...]")?;
    writeln!(
        w,
        "# top {TOP_N} phrases with multiple reading variants in phrases_composed.tsv"
    )?;
    writeln!(
        w,
        "# regeneratable — gitignored. Curated subset lives in heteronyms_curated.tsv."
    )?;
    for (ph, pys, freq) in results.iter().take(take) {
        writeln!(w, "{ph}\t{freq}\t{}", pys.join(","))?;
    }
    w.flush()?;

    eprintln!(
        "rows scanned: {total_rows}\n\
         phrases with >1 reading: {} (writing top {take})\n\
         output: {}",
        results.len(),
        dst.display()
    );
    Ok(())
}
