import re
from connection import prisma
from prisma.enums import Sentiment
from schemas import ProductCandidate, ProductAnalysisResult
import config
import ml_core
from fastapi import Request

def clean_product_name(name: str) -> str:
    name = re.sub(r'【.*?】', '', name)
    return name.strip()

async def process_product_reviews(candidate: ProductCandidate, user_email: str, metric_id: int, brand_id: int, request: Request):
    aspect_stats = {
        aspect: {"positive": 0, "total": 0} 
        for aspect in config.ASPECT_KEYWORDS.keys()
    }
    
    print(f"🔍 Memulai Analisis ABSA: {candidate.name[:30]}...")

    model_db = await prisma.model.find_first(where={"modelName": "Model XGBoost (Baseline)"})
    if not model_db:
        print("❌ ERROR: Model XGBoost tidak ditemukan di database!")
        return None
        
    user_db = await prisma.user.find_unique(where={"email": user_email})
    if not user_db:
        print(f"⚠️ User {user_email} tidak ditemukan!")
        return None

    brand_name = clean_product_name(candidate.name.split()[0]) if candidate.name.strip() else "Unknown"
    product_name = clean_product_name(candidate.name)

    product_db = await prisma.product.find_first(where={"url": candidate.url})
    if not product_db:
        product_db = await prisma.product.create(
            data={
                "name": product_name,
                "url": candidate.url,
                "brand": {
                    "connect_or_create": {
                        "where": {"name": brand_name}, 
                        "create": {"name": brand_name}
                    }
                },
            }
        )

    total_reviews = len(candidate.reviews)
    if total_reviews == 0: return None

    pos_count, neg_count = 0, 0
    reviews_data_to_save = []
    processed_texts_for_kwd = []

    for raw_text in candidate.reviews:
        if await request.is_disconnected():
            print(f"🛑 ABSA Dibatalkan di tengah jalan untuk {candidate.name}")
            return None
        
        clean_text = ml_core.preprocess_text(raw_text) 
        original_lower = raw_text.lower()      
        
        vec = ml_core.vectorizer.transform([clean_text])
        pred_idx = ml_core.model_optimized.predict(vec)[0]
        label = ml_core.label_encoder.inverse_transform([pred_idx])[0].lower()
        
        try:
            prob = ml_core.model_optimized.predict_proba(vec)[0]
            confidence_score = float(max(prob))
        except:
            confidence_score = 1.0

        is_positive = (label == "positif")
        if is_positive:
            pos_count += 1
            processed_texts_for_kwd.append(clean_text)
        else:
            neg_count += 1

        detected_keywords_from_review = [] 
        
        for aspect, keywords in config.ASPECT_KEYWORDS.items():
            matched_words = [k for k in keywords if k in original_lower or k in clean_text]
            
            if matched_words:
                detected_keywords_from_review.extend(matched_words)
                
                aspect_stats[aspect]["total"] += 1
                if is_positive:
                    aspect_stats[aspect]["positive"] += 1

        final_keywords = list(set(detected_keywords_from_review))

        reviews_data_to_save.append({
            "content": raw_text,
            "sentiment": Sentiment.POSITIVE if is_positive else Sentiment.NEGATIVE,
            "confidenceScore": confidence_score,
            "keywords": final_keywords,  
            "productId": product_db.productId,
            "modelId": model_db.modelId,    
            "userId": user_db.id
        })

    if reviews_data_to_save:
        async with prisma.tx() as transaction:
            await transaction.review.delete_many(where={"productId": product_db.productId})
            await transaction.review.create_many(data=reviews_data_to_save)

    final_aspect_scores = {}
    for aspect, stat in aspect_stats.items():
        score = (stat["positive"] / stat["total"] * 100) if stat["total"] > 0 else 0
        final_aspect_scores[aspect] = round(score, 1)

    general_sentiment_pct = (pos_count / total_reviews) * 100

    valid_aspects = {k: v for k, v in final_aspect_scores.items() if aspect_stats[k]["total"] > 0}
    
    if valid_aspects:
        best_aspect = max(valid_aspects, key=valid_aspects.get)
        worst_aspect = min(valid_aspects, key=valid_aspects.get)
        
        verdict_summary = f"Produk ini sangat unggul pada aspek {best_aspect.upper()}."
        if valid_aspects[worst_aspect] < 60:
            verdict_summary += f" Namun, pengguna sering mengeluhkan {worst_aspect.upper()}."
    else:
        verdict_summary = "Ulasan umum tidak spesifik membahas aspek teknis tertentu."

    if general_sentiment_pct > 80:
        verdict_label = "Sangat Direkomendasikan"
    elif general_sentiment_pct > 60:
        verdict_label = "Layak Dipertimbangkan"
    else:
        verdict_label = "Kurang Disarankan"

    new_analysis = await prisma.analysis.create(
        data={
            "userId": user_db.id,
        }
    )

    await prisma.metric.create(
        data={
            "generalSentiment": general_sentiment_pct,
            "compatibilityScore": general_sentiment_pct,
            "verdict": verdict_label,
            "topKeywords": [verdict_summary],
            "analysisId": new_analysis.analysisId,
            "productId": product_db.productId,
            "modelId": model_db.modelId,
        }
    )

    return ProductAnalysisResult(
        name=candidate.name, 
        url=candidate.url, 
        general_score=general_sentiment_pct,
        aspect_scores=final_aspect_scores, 
        total_reviews=total_reviews, 
        description=verdict_summary,
        positive_count=pos_count, 
        negative_count=neg_count, 
        verdict=verdict_label
    )