#!/usr/bin/env python3
"""
Match Figma cloud Drafts files (from figma-files.json) back to W{N} entries in
manifest.json by fuzzy name match, then update web/data.json with figma_key+url.
"""
import json, re, sys, difflib
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent

def normalize(s):
    s = s.lower()
    s = re.sub(r'[^a-z0-9]+', ' ', s).strip()
    return s

def best_match(target, candidates):
    """Return (score, candidate) best match from candidates list of dicts with .name"""
    nt = normalize(target)
    best = (0, None)
    for c in candidates:
        nc = normalize(c['name'])
        # exact / prefix / contains / sequence
        if nt == nc:                  s = 1.0
        elif nt in nc or nc in nt:    s = 0.85
        else:                         s = difflib.SequenceMatcher(None, nt, nc).ratio()
        if s > best[0]:
            best = (s, c)
    return best

def main():
    manifest = json.loads((ROOT/'manifest.json').read_text())
    figma_files_path = ROOT/'figma-files.json'
    if not figma_files_path.exists():
        print(f"missing {figma_files_path}", file=sys.stderr)
        sys.exit(1)
    figma_files = json.loads(figma_files_path.read_text())  # list of {key, name, ...}

    # Match each template source file to ALL matching cloud files (supports multi-variant)
    matches = []
    used_keys = set()
    for t in manifest['templates']:
        source_files = t['fig'] if t['fig'] else t['sketch']
        if not source_files: continue
        kind = 'fig' if t['fig'] else 'sketch'
        variants = []
        for src in source_files:
            stem = Path(src).stem
            # Match this specific source stem to best unused cloud file
            score, cand = best_match(stem, [f for f in figma_files if f['key'] not in used_keys])
            if cand and score >= 0.6:
                used_keys.add(cand['key'])
                variants.append({
                    'source_stem': stem,
                    'matched': cand['name'],
                    'key': cand['key'],
                    'score': round(score, 3)
                })
        matches.append({
            'W': t['id'], 'name': t['name'], 'kind': kind,
            'source_count': len(source_files),
            'variants': variants,
        })

    # Update web/data.json
    data_path = ROOT/'web'/'data.json'
    data = json.loads(data_path.read_text())
    by_W = {m['W']: m for m in matches}
    for t in data['templates']:
        m = by_W.get(t['id'])
        if m and m['variants']:
            first = m['variants'][0]
            t['figma_key'] = first['key']
            t['figma_url'] = f"https://www.figma.com/file/{first['key']}"
            t['figma_variants'] = [
                {'name': v['source_stem'], 'matched': v['matched'], 'key': v['key'],
                 'url': f"https://www.figma.com/file/{v['key']}"}
                for v in m['variants']
            ]
        else:
            t['figma_key'] = None
            t['figma_url'] = None
            t['figma_variants'] = []

    # update banner with imported count + variant total
    imported = sum(1 for t in data['templates'] if t['figma_key'])
    total_variants = sum(len(t.get('figma_variants', [])) for t in data['templates'])
    fig_cnt = sum(1 for t in manifest['templates'] if t['fig'])
    sketch_only_cnt = sum(1 for t in manifest['templates'] if not t['fig'] and t['sketch'])
    data['imported_summary'] = (
        f"✅ <b>{imported}/56 套</b>（共 {total_variants} 个文件）已云端就位在 "
        f"<a href='https://www.figma.com/files/team/1304178887825899477/drafts' target='_blank'>Figma Drafts</a>"
        f"（{fig_cnt} .fig + {sketch_only_cnt} .sketch 转换）。"
        f"点卡片 → modal → 多变体 tab 切换 + iframe 实时投射。"
    )
    data_path.write_text(json.dumps(data, ensure_ascii=False, indent=2))

    # write match report
    report = ROOT/'figma-match-report.json'
    report.write_text(json.dumps(matches, ensure_ascii=False, indent=2))
    total_matchable = sum(1 for t in manifest['templates'] if t['fig'] or t['sketch'])
    multi_variant = sum(1 for m in matches if len(m['variants']) > 1)
    print(f"Matched {imported}/{total_matchable} templates, {total_variants} total file keys, {multi_variant} with multi variants")
    print(f"Report: {report.relative_to(ROOT)}")
    unmatched = [m for m in matches if not m['variants']]
    if unmatched:
        print(f"\n⚠️  {len(unmatched)} unmatched:")
        for m in unmatched:
            print(f"  {m['W']:4s} {m['name'][:50]:50s}")

if __name__ == '__main__':
    main()
