#!/usr/bin/env python3
"""Извлекает описания метрик, зашитые в страницы отчётов halleg (local/Source/*.html + *_files/*.js).
Три паттерна: title="Имя — описание", showM('Имя','описание'), словари {n:"Имя", d:"описание"} / key:{n:..,d:..}.
Вывод: JSON-список {report, slug, name, description, pattern, key}."""
import re, json, glob, html, os, sys
SRC = os.path.join(os.path.dirname(__file__), '..', 'Source')
out = []
def slug_of(path):
    head = open(path, encoding='utf-8', errors='ignore').read(600)
    m = re.search(r'saved from url=\(\d+\)https?://[^/]+/([a-z0-9-]+)', head)
    return m.group(1) if m else None
for page in sorted(glob.glob(os.path.join(SRC, '*.html'))):
    slug = slug_of(page)
    if slug == 'metrics-legend': continue
    report = os.path.basename(page)[:-5]
    texts = [open(page, encoding='utf-8', errors='ignore').read()]
    for js in glob.glob(os.path.join(SRC, report.replace('_', ' ') + '_files', '*.js')):
        if re.search(r'/(sidebar|i18n[a-z]*)\.js$', js): continue
        texts.append(open(js, encoding='utf-8', errors='ignore').read())
    seen = set()
    def add(name, desc, pattern, key=None):
        name = html.unescape(name).strip(); desc = html.unescape(desc).strip()
        desc = re.sub(r'\s+', ' ', desc)
        if len(desc) < 12 or not name or (name, desc) in seen: return
        seen.add((name, desc))
        out.append(dict(report=report, slug=slug, name=name, description=desc, pattern=pattern, key=key))
    for s in texts:
        u = html.unescape(s)
        for m in re.finditer(r'title="([^"—]{1,40}) — ([^"]{12,})"', u):
            name = m.group(1).strip()
            # подсказки вида «Имя — описание»: имя это короткая подпись, а не кусок прозы
            # в Affiliate-отчётах подсказки «X — Y» это пояснения источников, а не метрики
            if report.startswith('Affiliate'): continue
            if len(name.split()) <= 5 and not re.search(r'[.,:;]', name):
                add(name, m.group(2), 'title')
        for m in re.finditer(r"showM\(\s*'((?:[^'\\]|\\.)+)'\s*,\s*'((?:[^'\\]|\\.)+)'", u): add(m.group(1), m.group(2), 'showM')
        for m in re.finditer(r'(?:([a-zA-Z0-9_]+)\s*:\s*)?\{\s*n\s*:\s*"((?:[^"\\]|\\.)+)"\s*(?:,\s*f\s*:\s*"[^"]*")?\s*,\s*d\s*:\s*"((?:[^"\\]|\\.)+)"', u): add(m.group(2), m.group(3), 'dict', m.group(1))
        # Retention & Churn: справка <div class="lg-m">Имя</div><div class="lg-d">описание
        for m in re.finditer(r'<div class="lg-m">(.*?)</div>\s*<div class="lg-d">(.*?)</div>\s*</div>', u, re.S):
            add(re.sub(r'<[^>]+>', '', m.group(1)), re.sub(r'<[^>]+>', ' ', m.group(2)), 'lg-item')
        # Affiliate Tier / Scoreboard: колонки {k:'x', l:'Имя', ..., tip:'описание'}
        for m in re.finditer(r"\{k:'([a-z_0-9]+)',\s*l:'([^']+)'[^}]*?tip:'((?:[^'\\]|\\.){12,})'", u):
            add(m.group(2), m.group(3), 'cols', m.group(1))
        # Affiliate Weekly: cTxt('Имя','key','tip') / cVal('Имя','group','tip',...)
        for m in re.finditer(r"\bc(?:Txt|Merged|Val|D|Pct|Num)\('([^']+)',\s*'[^']*',\s*'((?:[^'\\]|\\.){12,})'", u):
            add(m.group(1), m.group(2), 'colfn')
        # Hourly Calculator: { label: 'Имя', value: ..., tip: 'описание' }
        for m in re.finditer(r"\{\s*label:\s*'([^']+)',\s*value:[^,]+,\s*tip:\s*'((?:[^'\\]|\\.){12,})'", u):
            add(m.group(1), m.group(2), 'label-tip')
        # Merchant SLU: {k:'cr', t:'Total CR', f:pct, tip:["формула","источник","примечание"]}
        for m in re.finditer(r"\{k:'([a-z_0-9]+)',t:'([^']+)',f:[a-z]+,tip:\[(.*?)\]\}", u, re.S):
            parts = re.findall(r'"((?:[^"\\]|\\.)*)"', m.group(3))
            if parts:
                desc = parts[0] + ('. Джерело: ' + parts[1] if len(parts) > 1 else '') + ('. ' + parts[2] if len(parts) > 2 else '')
                add(m.group(2), desc, 'cols', m.group(1))
LEG = os.path.join(os.path.dirname(__file__), '..', 'in-progress', 'affiliate-dashboard', 'legend', 'data.js')
if os.path.exists(LEG):
    u = open(LEG, encoding='utf-8').read()
    seen = set()
    for m in re.finditer(r"\{\s*m:\s*'((?:[^'\\]|\\.)+)',\s*s:\s*'(\w+)',\s*d:\s*'((?:[^'\\]|\\.)+)'(?:,\s*q:\s*'((?:[^'\\]|\\.)+)')?", u, re.S):
        name, st, desc, q = m.group(1), m.group(2), m.group(3), m.group(4)
        desc = re.sub(r'<[^>]+>', '', html.unescape(desc)).replace("\\'", "'")
        if q: desc += ' [' + {'ok':'✓','warn':'⚠','none':'❌','req':'❓'}.get(st, st) + ' ' + re.sub(r'<[^>]+>', '', html.unescape(q)).replace("\\'", "'") + ']'
        out.append(dict(report='Affiliate_Dashboard', slug='trader-affiliate', name=name.replace("\\'", "'"), description=re.sub(r'\s+', ' ', desc), pattern='coverage-legend', key=st))
json.dump(out, open(os.path.join(os.path.dirname(__file__), '..', 'platform', 'data', '_raw_descriptions.json'), 'w'), ensure_ascii=False, indent=1)
from collections import Counter
c = Counter(o['report'] for o in out)
print(len(out), 'описаний;', len({o['name'] for o in out}), 'уникальных имён')
for k, v in c.most_common(): print(f'{v:4} {k}')
