#!/usr/bin/env python3
import sys
import json
import traceback
import re

def count_syllables(word):
    word = word.lower()
    count = 0
    vowels = "aeiouy"
    if len(word) == 0:
        return 0
    if word[0] in vowels:
        count += 1
    for index in range(1, len(word)):
        if word[index] in vowels and word[index - 1] not in vowels:
            count += 1
    if word.endswith("e"):
        count -= 1
    if count == 0:
        count = 1
    return count

def compute_flesch_kincaid(text):
    # Basic word tokenization
    words = re.findall(r'\b\w+\b', text)
    if not words:
        return 0.0
    
    # Sentence splitting (approximate)
    sentences = re.split(r'[.!?]+', text)
    sentences = [s.strip() for s in sentences if s.strip()]
    if not sentences:
        sentences = [text]
        
    num_words = len(words)
    num_sentences = len(sentences)
    num_syllables = sum(count_syllables(w) for w in words)
    
    asl = num_words / num_sentences
    asw = num_syllables / num_words
    
    grade = 0.39 * asl + 11.8 * asw - 15.59
    return round(max(0.0, min(18.0, grade)), 1)

def main():
    try:
        # Read JSON parameters from stdin
        input_data = json.load(sys.stdin)
        transcript = input_data.get('transcript', '')
        
        # 1. Load NLTK and initialize VADER
        import nltk
        from nltk.sentiment.vader import SentimentIntensityAnalyzer
        
        # Initialize VADER
        sia = SentimentIntensityAnalyzer()
        
        # Split into sentences using nltk
        sentences = nltk.sent_tokenize(transcript)
        
        sentiment_arc = []
        for idx, sentence in enumerate(sentences):
            sentence = sentence.strip()
            if not sentence:
                continue
            # Get VADER compound polarity score (-1.0 to +1.0)
            scores = sia.polarity_scores(sentence)
            compound = scores['compound']
            
            # Context-aware mapping using standard thresholds
            if compound >= 0.05:
                label = 'POSITIVE'
            elif compound <= -0.05:
                label = 'NEGATIVE'
            else:
                label = 'NEUTRAL'
                
            # Normalize compound score from [-1.0, 1.0] to [0.0, 1.0]
            normalized_score = float((compound + 1.0) / 2.0)
                
            sentiment_arc.append({
                'label': label,
                'score': normalized_score,
                'sentence': sentence,
                'sentence_index': idx
            })
            
        if not sentiment_arc:
            sentiment_arc.append({
                'label': 'NEUTRAL',
                'score': 0.5,
                'sentence': 'No speech recorded.',
                'sentence_index': 0
            })

        # 2. Semantic concepts similarity using Sentence-Transformers
        from sentence_transformers import SentenceTransformer, util
        
        # Use a lightweight fast embedding model
        model = SentenceTransformer('all-MiniLM-L6-v2')
        
        concepts = [
            {
                'concept': 'Value Proposition',
                'target_statements': [
                    'we offer automations to improve and speed up workflows',
                    'solves delays in shipping and coordinates partners',
                    'increases efficiency and value for companies'
                ]
            },
            {
                'concept': 'Pricing & Budget',
                'target_statements': [
                    'pricing plans subscription budgets and setup costs',
                    'how much it costs affordable pricing packages and investment return',
                    'budget options and financial details of onboarding'
                ]
            },
            {
                'concept': 'Implementation',
                'target_statements': [
                    'onboarding setup timeframes system integrations',
                    'launching the software setting up database connections',
                    'how to implement get started training the team'
                ]
            },
            {
                'concept': 'Closing Statement',
                'target_statements': [
                    'schedule next steps and book a follow up demo meeting',
                    'sign contract get started next week and closing the deal',
                    'call to action setting up a calendar invitation'
                ]
            }
        ]

        sales_concepts = []
        if transcript.strip() and sentences:
            # Embed entire transcript sentences for matching
            sentence_embeddings = model.encode(sentences, convert_to_tensor=True)
            
            for c in concepts:
                # Embed target concept statements
                target_embeddings = model.encode(c['target_statements'], convert_to_tensor=True)
                
                # Compute similarity matrix between all sentences and target statements
                sim_matrix = util.cos_sim(sentence_embeddings, target_embeddings)
                
                # Find the best matching sentence indices and scores
                max_sim = float(sim_matrix.max())
                detected = max_sim >= 0.40
                
                evidence_sentence = ""
                if detected:
                    # Get index of sentence with highest similarity
                    import numpy as np
                    flat_idx = int(sim_matrix.cpu().numpy().argmax())
                    sent_idx = flat_idx // len(c['target_statements'])
                    if sent_idx < len(sentences):
                        evidence_sentence = sentences[sent_idx]
                
                sales_concepts.append({
                    'concept': c['concept'],
                    'detected': detected,
                    'confidence': max_sim,
                    'evidence_sentence': evidence_sentence
                })
        else:
            for c in concepts:
                sales_concepts.append({
                    'concept': c['concept'],
                    'detected': False,
                    'confidence': 0.0,
                    'evidence_sentence': ""
                })

        # 3. Readability & Power Words
        flesch_grade = compute_flesch_kincaid(transcript)
        
        # Match power words
        power_words_list = [
            'value', 'revenue', 'growth', 'solution', 'results', 'guarantee', 
            'discover', 'proven', 'save', 'efficient', 'optimize', 'speed', 
            'increase', 'improve', 'maximize', 'seamless', 'instant'
        ]
        lower_transcript = transcript.lower()
        power_word_hits = []
        for pw in power_words_list:
            if re.search(r'\b' + re.escape(pw) + r'\b', lower_transcript):
                power_word_hits.append(pw.capitalize())

        # Match top keywords (highest frequency nouns/adjectives)
        from nltk.corpus import stopwords
        try:
            stop_words = set(stopwords.words('english'))
        except Exception:
            # Download stopwords if not present
            nltk.download('stopwords')
            stop_words = set(stopwords.words('english'))
            
        words_filtered = [w for w in re.findall(r'\b\w+\b', lower_transcript) if w not in stop_words and len(w) > 2]
        
        # Count frequencies
        freq = {}
        for w in words_filtered:
            freq[w] = freq.get(w, 0) + 1
        top_keywords = sorted(freq, key=freq.get, reverse=True)[:5]
        top_keywords = [w.capitalize() for w in top_keywords]

        # Output results
        result = {
            'status': 'success',
            'sentiment_arc': sentiment_arc,
            'sales_concepts': sales_concepts,
            'flesch_kincaid_grade': flesch_grade,
            'power_word_hits': power_word_hits,
            'top_keywords': top_keywords
        }
        print(json.dumps(result))

    except Exception as e:
        error_details = {
            'status': 'error',
            'error': str(e),
            'traceback': traceback.format_exc()
        }
        print(json.dumps(error_details), file=sys.stderr)
        sys.exit(1)

if __name__ == '__main__':
    main()
