#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Înlocuiește coloana `comment` din frugal_pain_points.csv cu comentariul original
căutat în r_intj_comments.csv DOAR pe baza fragmentelor din `quotes`.

- quotes poate conține unul sau mai multe fragmente (ex: separate prin " || " sau ";")
- potrivirea este exactă (verbatim substring), fără case folding (dar poți activa opțiunea)
- dacă sunt mai multe potriviri în fișierul de comentarii, se alege cea cu
  cele mai multe fragmente potrivite, iar la egalitate, comentariul cel mai lung

Exemplu:
    python match_by_quotes.py \
        --pain-points frugal_pain_points.csv \
        --comments r_intj_comments.csv \
        --output frugal_pain_points_with_full_comments.csv \
        --keep-excerpt
"""

import argparse
import sys
import re
import pandas as pd
from typing import List, Optional


def split_quotes(raw: str) -> List[str]:
    """
    Împarte coloana quotes în fragmente individuale.
    Suportă separatori comuni: '||', ';', '|', newline.
    Păstrează spațiile interne, dar taie spațiile la capete.
    Elimină golurile.
    """
    if not isinstance(raw, str) or not raw.strip():
        return []
    # separatori: || ; | \n
    parts = re.split(r"\|\||\n|;|\|", raw)
    return [p.strip() for p in parts if p and p.strip()]


def best_match_for_quotes(quotes: List[str], comments_series: pd.Series, case_insensitive: bool = False) -> Optional[str]:
    """
    Găsește comentariul 'cel mai bun' care conține cât mai multe fragmente din `quotes`.
    Reguli:
      1) scor = numărul de fragmente care apar ca substring în comentariu
      2) tie-breaker: lungimea comentariului (mai lung = preferat)
    Returnează textul comentariului sau None dacă nu există potrivire.
    """
    if not quotes:
        return None

    # pregătește pattern-urile
    patterns = []
    flags = re.IGNORECASE if case_insensitive else 0
    for q in quotes:
        try:
            patterns.append(re.compile(re.escape(q), flags))
        except re.error:
            # dacă ceva e ciudat în q (rareori), sari peste
            continue
    if not patterns:
        return None

    best_idx = None
    best_score = -1
    best_len = -1

    # iterare vectorizată: creăm o mască pentru fiecare citat și sumăm potrivirile
    # pentru simplitate și claritate, iterăm în Python; pentru seturi foarte mari se poate optimiza
    for idx, text in comments_series.items():
        if not isinstance(text, str):
            continue
        score = 0
        for pat in patterns:
            if pat.search(text) is not None:
                score += 1
        if score > 0:
            L = len(text)
            if score > best_score or (score == best_score and L > best_len):
                best_idx = idx
                best_score = score
                best_len = L

    if best_idx is None:
        return None
    return comments_series.loc[best_idx]


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--pain-points", required=True, help="CSV cu pain points (ex: frugal_pain_points.csv)")
    ap.add_argument("--comments", required=True, help="CSV cu comentariile originale (ex: r_intj_comments.csv)")
    ap.add_argument("--output", required=True, help="Fișierul CSV de ieșire")
    ap.add_argument("--keep-excerpt", action="store_true",
                    help="Păstrează vechiul `comment` ca `comment_excerpt`")
    ap.add_argument("--case-insensitive", action="store_true",
                    help="Căutare case-insensitive pentru potrivirea fragmentelor din quotes")
    args = ap.parse_args()

    try:
        df_pp = pd.read_csv(args.pain_points)
    except Exception as e:
        print(f"❌ Eroare la citirea pain points: {e}", file=sys.stderr)
        sys.exit(1)

    try:
        df_c = pd.read_csv(args.comments)
    except Exception as e:
        print(f"❌ Eroare la citirea comments: {e}", file=sys.stderr)
        sys.exit(1)

    # verificăm coloanele esențiale
    if "quotes" not in df_pp.columns:
        print("❌ Lipseste coloana 'quotes' din pain points.", file=sys.stderr)
        sys.exit(1)
    if "comment" not in df_c.columns:
        print("❌ Lipseste coloana 'comment' din fișierul de comentarii.", file=sys.stderr)
        sys.exit(1)

    # optional: păstrăm excerpt-ul
    if args.keep_exceprt if hasattr(args, "keep_exceprt") else args.keep_excerpt:
        if "comment" in df_pp.columns:
            df_pp = df_pp.rename(columns={"comment": "comment_excerpt"})
    else:
        if "comment" in df_pp.columns:
            df_pp = df_pp.drop(columns=["comment"])

    # pregătim o listă din coloana comment pentru căutare
    comments_series = df_c["comment"].astype(str)

    # pentru fiecare rând din pain points, găsește comentariul original
    full_comments = []
    full_urls = []
    unmatched_rows = 0

    for i, row in df_pp.iterrows():
        qlist = split_quotes(row.get("quotes", ""))
        match = best_match_for_quotes(qlist, df_c["comment"], case_insensitive=args.case_insensitive)

        if match is None:
            unmatched_rows += 1
            full_comments.append(None)
            full_urls.append(None)
        else:
            # găsește rândul complet în df_c
            matched_row = df_c[df_c["comment"] == match].iloc[0]
            full_comments.append(matched_row["comment"])
            full_urls.append(matched_row["post_url"])

    # adaugă/înlocuiește coloanele comment și post_url
    df_pp["comment"] = full_comments
    df_pp["post_url"] = full_urls

    # reordonează coloanele pentru lizibilitate
    preferred_order = [c for c in ["comment_id", "comment", "quotes"] if c in df_pp.columns]
    other_cols = [c for c in df_pp.columns if c not in preferred_order]
    df_pp = df_pp[preferred_order + other_cols]

    # salvează
    try:
        df_pp.to_csv(args.output, index=False, encoding="utf-8")
    except Exception as e:
        print(f"❌ Eroare la scrierea fișierului de ieșire: {e}", file=sys.stderr)
        sys.exit(1)

    total = len(df_pp)
    print(f"✅ Salvat: {args.output}")
    if unmatched_rows:
        print(f"ℹ️ {unmatched_rows}/{total} rânduri fără potrivire bazată pe `quotes`.")
        print("   Verifică dacă fragmentele din `quotes` există ca substring în fișierul de comentarii.")
        print("   Poți încerca și --case-insensitive dacă diferențele sunt doar de majuscule.")


if __name__ == "__main__":
    main()
