"""
BSS Skill: Customer Feedback Synthesizer
Parses a batch of customer feedback items (reviews, NPS responses, support tickets,
survey answers) and outputs sentiment distribution, top themes, praise highlights,
and complaints. Reduces feedback batches by 80-92%.
"""
import re
import collections

text = PROMPT  # injected by BIBIVIDI sandbox wrapper

# ── Positive / negative keyword lists ─────────────────────────────────────────

POSITIVE_KEYWORDS = [
    'excellent', 'great', 'love', 'perfect', 'amazing', 'awesome',
    'highly recommend', 'fantastic', 'wonderful', 'helpful', 'easy', 'fast',
    'efficient', 'satisf', 'happy', 'impressed', 'super',
    'génial', 'parfait', 'rapide', 'facile', 'satisfait', 'recommande',
    'top', 'bravo',
]

NEGATIVE_KEYWORDS = [
    'terrible', 'awful', 'worst', 'hate', 'broken', 'useless', 'slow',
    'confusing', 'disappointed', 'frustrated', 'poor', 'bad', 'never again',
    'waste', 'bug', 'crash',
    'nul', 'mauvais', 'lent', 'difficile', 'déçu', 'frustrant',
    'problème', 'pire', 'horrible',
]

# ── Theme keyword clusters ─────────────────────────────────────────────────────

THEMES = {
    'Performance':  ['slow', 'fast', 'speed', 'latency', 'performance', 'lent', 'rapide', 'vitesse'],
    'UX/Design':    ['interface', 'ui', 'design', 'navigation', 'confusing', 'intuitive', 'layout', 'ergonomie'],
    'Support':      ['support', 'help', 'response', 'team', 'agent', 'customer service', 'service client'],
    'Pricing':      ['price', 'expensive', 'cheap', 'value', 'cost', 'pricing', 'prix', 'cher', 'abordable'],
    'Features':     ['feature', 'missing', 'request', 'add', 'fonctionnalité', 'manque'],
    'Reliability':  ['bug', 'crash', 'error', 'broken', 'down', 'stable', 'reliable', 'fiable'],
    'Onboarding':   ['setup', 'install', 'onboard', 'getting started', 'tutorial', 'documentation', 'guide'],
}


# ── Parsing helpers ────────────────────────────────────────────────────────────

def split_feedback_items(txt):
    """Split text into individual feedback items using various separator conventions."""
    items = []

    # Numbered: "1. ...", "2. ..."
    numbered = re.split(r'(?m)^\s*\d+\.\s+', txt)
    if len(numbered) > 2:
        items = [s.strip() for s in numbered if s.strip()]
        return [i for i in items if len(i) >= 10][:50]

    # Dashed or === separator lines
    dashed = re.split(r'(?m)^(?:---+|===+)\s*$', txt)
    if len(dashed) > 1:
        items = [s.strip() for s in dashed if s.strip()]
        return [i for i in items if len(i) >= 10][:50]

    # Review:/Feedback:/Comment:/Avis: prefix
    prefixed = re.split(r'(?m)^(?:Review|Feedback|Comment|Avis)\s*:\s*', txt, flags=re.IGNORECASE)
    if len(prefixed) > 1:
        items = [s.strip() for s in prefixed if s.strip()]
        return [i for i in items if len(i) >= 10][:50]

    # Quoted blocks: lines starting with "
    quote_blocks = re.findall(r'"([^"]{10,})"', txt)
    if len(quote_blocks) >= 2:
        return quote_blocks[:50]

    # Fallback: double-newline paragraphs
    paragraphs = re.split(r'\n\s*\n', txt)
    items = [p.strip() for p in paragraphs if p.strip()]
    return [i for i in items if len(i) >= 10][:50]


def classify_sentiment(txt):
    """Return 'positive', 'negative', or 'neutral' based on keyword scoring."""
    lower = txt.lower()
    score = 0
    for kw in POSITIVE_KEYWORDS:
        if kw in lower:
            score += 1
    for kw in NEGATIVE_KEYWORDS:
        if kw in lower:
            score -= 1
    if score > 0:
        return 'positive'
    if score < 0:
        return 'negative'
    return 'neutral'


def _keyword_density(txt, keywords):
    """Count how many of the given keywords appear in txt."""
    lower = txt.lower()
    return sum(1 for kw in keywords if kw in lower)


def extract_themes(items):
    """Find recurring themes across items; return themes with >= 2 mentions, sorted desc."""
    counts = collections.Counter()
    for item in items:
        lower = item.lower()
        for theme, keywords in THEMES.items():
            if any(kw in lower for kw in keywords):
                counts[theme] += 1
    return [(theme, count) for theme, count in counts.most_common() if count >= 2]


def get_highlights(items, sentiments, n_pos=2, n_neg=2):
    """Return top positive and top negative items by keyword density."""
    scored_pos = []
    scored_neg = []
    for item, sentiment in zip(items, sentiments):
        if sentiment == 'positive':
            density = _keyword_density(item, POSITIVE_KEYWORDS)
            scored_pos.append((density, item))
        elif sentiment == 'negative':
            density = _keyword_density(item, NEGATIVE_KEYWORDS)
            scored_neg.append((density, item))

    scored_pos.sort(key=lambda x: x[0], reverse=True)
    scored_neg.sort(key=lambda x: x[0], reverse=True)

    top_pos = [item[:120] for _, item in scored_pos[:n_pos]]
    top_neg = [item[:120] for _, item in scored_neg[:n_neg]]
    return top_pos, top_neg


def get_nps_score(txt):
    """Extract NPS / rating scores and return their average, or None if none found."""
    scores = []

    # "NPS: 42" / "Net Promoter Score: 7"
    for m in re.finditer(r'(?:NPS|Net Promoter Score)\s*[:\-]\s*(\d+(?:\.\d+)?)', txt, re.IGNORECASE):
        scores.append(float(m.group(1)))

    # "score: 8/10"
    for m in re.finditer(r'\bscore\s*[:\-]\s*(\d+(?:\.\d+)?)\s*/\s*(\d+)', txt, re.IGNORECASE):
        val, out_of = float(m.group(1)), float(m.group(2))
        if out_of > 0:
            scores.append(val / out_of * 10)

    # "4/5", "3/10" standalone ratings
    for m in re.finditer(r'\b(\d+(?:\.\d+)?)\s*/\s*(5|10)\b', txt):
        val, out_of = float(m.group(1)), float(m.group(2))
        if val <= out_of:
            scores.append(val / out_of * 10)

    # "3 stars" / "★★★"
    for m in re.finditer(r'(\d)\s*stars?', txt, re.IGNORECASE):
        scores.append(float(m.group(1)) / 5 * 10)
    star_blocks = re.findall(r'[★]{1,5}', txt)
    for block in star_blocks:
        scores.append(len(block) / 5 * 10)

    if not scores:
        return None
    return round(sum(scores) / len(scores), 1)


# ── Parse & output ─────────────────────────────────────────────────────────────

items      = split_feedback_items(text)
sentiments = [classify_sentiment(item) for item in items]
themes     = extract_themes(items)
pos_items, neg_items = get_highlights(items, sentiments)
nps        = get_nps_score(text)

n_total   = len(items)
n_pos     = sentiments.count('positive')
n_neu     = sentiments.count('neutral')
n_neg     = sentiments.count('negative')
pos_pct   = round(n_pos / n_total * 100) if n_total else 0

lines = ['=== BIBIVIDI: CUSTOMER FEEDBACK ===']
lines.append(f'Items    : {n_total}')
lines.append(f'Sentiment: {n_pos} positive, {n_neu} neutral, {n_neg} negative ({pos_pct}% positive)')
if nps is not None:
    lines.append(f'NPS/Score: {nps}')

if themes:
    lines.append('\n[TOP THEMES]')
    for theme, count in themes:
        lines.append(f'  - {theme} ({count} mentions)')

if pos_items:
    lines.append('\n[PRAISE]')
    for highlight in pos_items:
        lines.append(f'  - "{highlight}"')

if neg_items:
    lines.append('\n[COMPLAINTS]')
    for highlight in neg_items:
        lines.append(f'  - "{highlight}"')

lines.append(f'\n=== END (condensed from {len(text)} chars) ===')

print('\n'.join(lines))
