"""Кросс-доменный детектор мусора по ВСЕМ сферам (не только IT), с учётом
смежности. Вакансия классифицируется по ЯВНОМУ маркеру в ЗАГОЛОВКЕ (надёжно);
профиль, матчащий вакансию ДАЛЁКОЙ (не смежной) группы = мусор."""
import re
import sqlite3
import sys

sys.path.insert(0, ".")
from bot.vacancy_filters import matches_vacancy_relevance, normalize_text

con = sqlite3.connect("file:vakhunter.db?mode=ro", uri=True)
con.row_factory = sqlite3.Row
ROWS = [dict(r) for r in con.execute(
    "SELECT title,description,source,skills FROM vacancies "
    "WHERE created_at>datetime('now','-21 days')").fetchall()]

# Группа вакансии по маркеру в ЗАГОЛОВКЕ (порядок = приоритет).
GROUP_MARKERS = [
    ("it", r"разработчик|программист|developer|backend|frontend|fullstack|devops|"
           r"тестировщик|\bqa\b|python|java(?!scr)|golang|верстальщик|аналитик данных|"
           r"数据|data scientist|системный администратор|сисадмин|1c developer"),
    ("med", r"врач|медсестр|медбрат|фельдшер|фармацевт|провизор|ветеринар|санитар|"
            r"стоматолог|ортодонт|хирург|терапевт|педиатр|акушер"),
    ("beauty", r"парикмахер|косметолог|маникюр|педикюр|массажист|визажист|бровист|"
               r"лашмейкер|стилист|эпиляц"),
    ("edu", r"учитель|преподавател|репетитор|воспитател|педагог|методист|тьютор|"
            r"логопед|дефектолог"),
    ("finance", r"бухгалтер|экономист|аудитор|финансов|казначе"),
    ("legal", r"юрист|адвокат|нотариус|юрисконсульт"),
    ("food", r"повар|официант|бармен|бариста|кондитер|пекарь|хостес|посудомой|шеф-повар|су-шеф"),
    ("auto", r"автомеханик|автослесар|автомойщик|шиномонт|автоэлектрик|моторист|автомаляр"),
    ("construction", r"сварщик|электрик|сантехник|\bмаляр|плиточник|штукатур|каменщик|"
                     r"монтажник|токарь|слесар|фрезеров|столяр|бетонщик|арматурщик|"
                     r"кровельщик|отделочник|разнорабоч|электромонтаж|электрогазосвар"),
    ("logistics", r"водител|курьер|экспедитор|\bлогист|кладовщик|комплектовщик|грузчик|"
                  r"таксист|диспетчер|дальнобой"),
    ("trade", r"продавец|кассир|мерчендайзер|мерчандайзер|товаровед"),
    ("beauty_health", r"фитнес|тренер"),
    ("security_clean", r"охранник|сторож|уборщи|клинер|дворник|горничн|консьерж|вахтер"),
    ("sales_office", r"менеджер по продаж|hr-|рекрутер|секретар|оператор колл|"
                     r"маркетолог|\bsmm|копирайтер|дизайнер|таргетолог"),
]
COMPILED = [(g, re.compile(p, re.I)) for g, p in GROUP_MARKERS]

def vac_group(title):
    for g, rx in COMPILED:
        if rx.search(title or ""):
            return g
    return None

# Смежные пары (допустимо матчить, НЕ мусор).
ADJ = {frozenset(x) for x in [
    ("construction", "auto"), ("construction", "logistics"),
    ("construction", "security_clean"), ("food", "trade"),
    ("beauty", "beauty_health"), ("beauty", "med"),
    ("finance", "legal"), ("finance", "sales_office"), ("legal", "sales_office"),
    ("trade", "sales_office"), ("it", "sales_office"), ("logistics", "trade"),
    ("logistics", "security_clean"), ("auto", "logistics"),
    ("med", "beauty_health"), ("edu", "sales_office"),
]}

# профиль → его группа
PROFILES = [
    ("Официант", "ресторан, обслуживание", "food"),
    ("Повар", "кухня, блюда", "food"),
    ("Продавец", "торговый зал", "trade"),
    ("Кассир", "касса", "trade"),
    ("Водитель", "категория B", "logistics"),
    ("Курьер", "доставка", "logistics"),
    ("Сварщик", "аргонная сварка", "construction"),
    ("Электрик", "монтаж проводки", "construction"),
    ("Сантехник", "установка сантехники", "construction"),
    ("Маляр", "покраска, отделка", "construction"),
    ("Грузчик", "погрузка", "logistics"),
    ("Автомеханик", "ремонт двигателя", "auto"),
    ("Парикмахер", "стрижки, окрашивание", "beauty"),
    ("Косметолог", "уход, процедуры", "beauty"),
    ("Массажист", "лечебный массаж", "beauty"),
    ("Медсестра", "уколы, стационар", "med"),
    ("Врач-терапевт", "приём пациентов", "med"),
    ("Бухгалтер", "1С, первичка, отчётность", "finance"),
    ("Экономист", "планирование, бюджет", "finance"),
    ("Юрист", "договоры, суд", "legal"),
    ("Учитель математики", "подготовка к ЕГЭ", "edu"),
    ("Репетитор английского", "английский", "edu"),
    ("Воспитатель", "работа с детьми в саду", "edu"),
    ("Охранник", "охрана объекта", "security_clean"),
    ("Уборщица", "уборка помещений", "security_clean"),
    ("Швея", "пошив, машина", "construction"),
    ("Флорист", "букеты, цветы", "trade"),
]

garbage = {}
for sp, sk, pg in PROFILES:
    for v in ROWS:
        vg = vac_group(v["title"])
        if not vg or vg == pg:
            continue
        if frozenset((pg, vg)) in ADJ:
            continue
        if matches_vacancy_relevance(sp, sk, v):
            garbage.setdefault(f"{sp} [{pg}]", []).append(f"[{vg}] {v['title'][:52]} ({v['source']})")

total = sum(len(x) for x in garbage.values())
grp = sum(1 for v in ROWS if vac_group(v["title"]))
print(f"Классифицировано вакансий по заголовку: {grp}/{len(ROWS)}; профилей: {len(PROFILES)}")
print(f"\n{'='*64}\n🟥 КРОСС-ДОМЕННЫЙ МУСОР (не смежные сферы): {total}\n{'='*64}")
for prof, items in sorted(garbage.items(), key=lambda x: -len(x[1])):
    print(f"\n  {prof}  ({len(items)}):")
    for it in items[:8]:
        print(f"      ⚠ {it}")
if not garbage:
    print("✅ ЧИСТО")
