from pathlib import Path
import pdfplumber, re
from collections import defaultdict

HEADER_HINTS = ("Pos.", "Text", "Menge", "Preis", "Summe")

def _is_header_row(row_texts: list[str]) -> bool:
    j = " ".join(x or "" for x in row_texts)
    return all(h.lower() in j.lower() for h in ("pos", "text", "menge")) and ("preis" in j.lower() or "summe" in j.lower())

def parse_lv_tables_from_pdf(pdf_path: Path) -> dict:
    """
    Returns: dict[pos_code] = {'EP': float|None, 'GP': float|None, 'text': '...'}
    Heuristik: wir suchen Tabellen mit Header (Pos/Text/Menge/Preis/Summe).
    Danach mappen wir Zahlen in 'Preis'/'Summe' auf die zuletzt gesehene 'Pos.'.
    """
    data = {}
    last_pos = None
    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            try:
                tables = page.extract_tables()
            except Exception:
                tables = []
            # Wenn Tabellen leer, ggf. später OCR-Fallback
            for tbl in tables or []:
                # Normalisieren
                tbl = [[(c or "").strip() for c in row] for row in tbl]
                if not tbl: 
                    continue
                # Header finden
                header_idx = None
                for i, row in enumerate(tbl[:5]):
                    if _is_header_row(row):
                        header_idx = i
                        break
                if header_idx is None:
                    continue
                header = tbl[header_idx]
                colmap = {name.lower(): idx for idx,name in enumerate(header)}
                # Spalten indices heuristisch
                def idx_of(keys): 
                    for k in keys:
                        for i,name in enumerate(header):
                            if k.lower() in (name or "").lower():
                                return i
                    return None
                pos_i = idx_of(["Pos", "Pos."])
                txt_i = idx_of(["Text"])
                menge_i = idx_of(["Menge"])
                preis_i = idx_of(["Preis"])
                sum_i = idx_of(["Summe", "Total"])
                for row in tbl[header_idx+1:]:
                    pos = row[pos_i] if pos_i is not None and pos_i < len(row) else ""
                    txt = row[txt_i] if txt_i is not None and txt_i < len(row) else ""
                    preis = row[preis_i] if preis_i is not None and preis_i < len(row) else ""
                    summ = row[sum_i] if sum_i is not None and sum_i < len(row) else ""

                    if re.fullmatch(r'\d{1,4}', pos or ""):
                        last_pos = pos
                        data.setdefault(last_pos, {'EP': None, 'GP': None, 'text': ""})
                        if txt: 
                            data[last_pos]['text'] = (data[last_pos]['text'] + " " + txt).strip()
                    elif txt and last_pos:
                        # Detailzeile (Bullet) → enthält evtl. Preis/Summe
                        data[last_pos]['text'] = (data[last_pos]['text'] + " " + txt).strip()

                    def to_num(s):
                        s = (s or "").replace("'", "").replace("’","").replace(" ", "").replace("CHF","").replace("Fr.","")
                        s = s.replace("–","-").replace("—","-")
                        s = s.replace(",", ".")
                        try:
                            return float(s)
                        except:
                            return None

                    ep = to_num(preis)
                    gp = to_num(summ)
                    if last_pos:
                        if ep is not None: data[last_pos]['EP'] = ep
                        if gp is not None: data[last_pos]['GP'] = gp
    return data
