#!/usr/bin/env python3
"""
Парсинг Excel-выгрузки из Bitrix24 (формат HTML-таблица, расширение .xls).
Результат: data/excel_records.json

Использование:
    python3 parse_excel.py <путь_к_файлу.xls>
"""

import json
import os
import re
import sys
from html.parser import HTMLParser


# --- Паттерны (те же что в fetch_api.py) ---
PAYER_MAP  = {'373': 'БДК', '375': 'ТЗК', '377': 'ИНГЕО', '1059': 'ВЦПО'}
STATUS_MAP = {
    '363': 'Отклонено',
    '365': 'Согласовано',
    '367': 'Согласовано и распечатано',
    '419': 'Не установлен',
}

DOC_PATTERNS = [
    ('КС-2/КС-3',    r'КС-2\s*/\s*КС-3'),
    ('УПД',          r'\bУПД\b'),
    ('Счет-фактура', r'[Сс]чет-фактура|[Сс]ч-ф\b'),
    ('Акт',          r'\bАкт\b'),
    ('Счет',         r'[Сс]чет\s*№'),
    ('КС-2',         r'КС-2\b'),
    ('КС-3',         r'КС-3\b'),
    ('Справка',      r'[Сс]правка'),
    ('Договор',      r'Дог(?:овор)?\.?\s*№'),
    ('ДС',           r'\bДС\s*№'),
]


class TableParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.rows         = []
        self.current_row  = []
        self.current_cell = ''
        self.in_cell      = False

    def handle_starttag(self, tag, attrs):
        if tag in ('td', 'th'):
            self.in_cell      = True
            self.current_cell = ''
        elif tag == 'tr':
            self.current_row = []

    def handle_endtag(self, tag):
        if tag in ('td', 'th'):
            self.current_row.append(self.current_cell.strip())
            self.in_cell = False
        elif tag == 'tr':
            if any(c.strip() for c in self.current_row):
                self.rows.append(self.current_row)

    def handle_data(self, data):
        if self.in_cell:
            self.current_cell += data


def parse_doc_types(text: str) -> list:
    found = []
    for name, pat in DOC_PATTERNS:
        if re.search(pat, text or ''):
            found.append(name)
    return list(dict.fromkeys(found))


def extract_contract_refs(text: str) -> list:
    refs = []
    for m in re.findall(r'к\s*Договору\s*№\s*([\w\d\.\-\/]+)', text or ''):
        refs.append('Договор №' + m)
    for m in re.findall(r'по\s*ДС\s*№\s*([\w\d\.]+)', text or ''):
        refs.append('ДС №' + m)
    return refs


def parse_file(path: str) -> list:
    with open(path, 'r', encoding='utf-8-sig', errors='replace') as f:
        content = f.read()

    parser = TableParser()
    parser.feed(content)

    if not parser.rows:
        raise ValueError('Таблица не найдена в файле')

    headers = parser.rows[0]

    # Индексы столбцов по имени
    def col(name):
        for i, h in enumerate(headers):
            if name.lower() in h.lower():
                return i
        return None

    idx = {
        'id':          col('ID'),
        'name':        col('Название'),
        'num_date':    col('Номер, дата'),
        'contractor':  col('Наименование контрагента'),
        'doc_type':    col('Тип документа'),
        'amount':      col('Сумма'),
        'status':      col('Статус'),
        'date_create': col('Дата инициации'),
        'payer':       col('Плательщик'),
        'comment':     col('Комментарий (разъяснение)'),
    }

    print('Найденные столбцы:')
    for k, v in idx.items():
        print(f'  {k:15} → [{v}] {headers[v] if v is not None else "НЕ НАЙДЕН"}')

    records = []
    for row in parser.rows[1:]:
        def g(i):
            return row[i].strip() if i is not None and i < len(row) else ''

        element_id = g(idx['id'])
        if not element_id:
            continue

        nom_dat   = g(idx['num_date'])
        title     = g(idx['name'])
        doc_types = parse_doc_types(nom_dat) or parse_doc_types(title)

        records.append({
            'element_id':    element_id,
            'name':          title,
            'date_create':   g(idx['date_create'])[:10],
            'contractor':    g(idx['contractor']),
            'payer':         g(idx['payer']),
            'doc_type_raw':  g(idx['doc_type']),
            'doc_types':     doc_types,
            'contract_refs': extract_contract_refs(nom_dat),
            'num_date_str':  nom_dat,
            'amount':        g(idx['amount']),
            'status':        g(idx['status']),
            'comment':       g(idx['comment']),
            # Файловые ID в Excel-выгрузке недоступны — заполняются при матче с API
            'file_ids':      [],
            'file_count':    0,
            'has_analysis':  False,
            'source':        'excel',
        })

    return records


def main():
    if len(sys.argv) < 2:
        # Ищем любой .xls в текущей папке
        candidates = [f for f in os.listdir('.') if f.endswith('.xls') or f.endswith('.xlsx')]
        if not candidates:
            print('Укажите путь к файлу: python3 parse_excel.py <файл.xls>')
            sys.exit(1)
        path = candidates[0]
        print(f'Найден файл: {path}')
    else:
        path = sys.argv[1]

    print(f'Парсю: {path}')
    records = parse_file(path)

    os.makedirs('data', exist_ok=True)
    out_path = 'data/excel_records.json'
    with open(out_path, 'w', encoding='utf-8') as f:
        json.dump(records, f, ensure_ascii=False, indent=2)

    print(f'\n✅ Сохранено: {out_path}')
    print(f'   Записей:         {len(records)}')
    print(f'   С реф. договора: {sum(1 for r in records if r["contract_refs"])}')
    print(f'   Без типа:        {sum(1 for r in records if not r["doc_types"])}')

    from collections import Counter
    ct = Counter(t for r in records for t in r['doc_types'])
    print('\n   Типы документов:')
    for t, n in ct.most_common():
        print(f'     {n:3}x  {t}')

    print('\n   Примеры:')
    for r in records[:3]:
        print(f'   [{r["element_id"]}] {r["name"][:60]}')
        print(f'          типы: {r["doc_types"]} | контрагент: {r["contractor"]}')


if __name__ == '__main__':
    main()
