from fastapi import HTTPException
import logging
from sqlalchemy.orm import Session
from sqlalchemy import func
import time
from src.core.recommendation_agent import RecommendationAgent
from src.utils.models import Feedback, ReviewTopic, Emotion, Word, Recommendation
import instructor
import openai
import os
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Fetch environment variables
API_KEY = os.getenv("AZURE_OPENAI_API_KEY")
ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT")
DEPLOYMENT = os.getenv("AZURE_OPENAI_DEPLOYMENT")
API_VERSION = os.getenv("AZURE_OPENAI_API_VERSION")

# Initialize OpenAI client
client = instructor.from_openai(openai.AzureOpenAI(
    api_key=API_KEY,
    api_version=API_VERSION,
    azure_endpoint=ENDPOINT,
    azure_deployment=DEPLOYMENT
))

rec_agent = RecommendationAgent(client=client)

def generate_aggregated_feedback(db: Session, branch_id: int):
    """
    Generate aggregated feedback insights for a specific branch.
    """
    total_reviews = db.query(Feedback).filter(Feedback.branch_id == branch_id).count()
    #logging.info(f"Total reviews for branch {branch_id}: {total_reviews}")

    sentiment_counts = db.query(
        Feedback.sentiment, func.count(Feedback.sentiment)
    ).filter(Feedback.branch_id == branch_id).group_by(Feedback.sentiment).all()

    sentiment_breakdown = {sent: count for sent, count in sentiment_counts}
    #logging.info(f"Sentiment breakdown: {sentiment_breakdown}")

    if total_reviews > 0:
        overall_sentiment_score = round((
            ((sentiment_breakdown.get("positive", 0) * 100) +
             (sentiment_breakdown.get("neutral", 0) * 50) +
             (sentiment_breakdown.get("negative", 0) * 0) +
             (sentiment_breakdown.get("mixed", 0) * 25)) / total_reviews
        ))
    else:
        overall_sentiment_score = 0

    #logging.info(f"Overall sentiment score: {overall_sentiment_score}")

    topic_sentiment = {}
    topic_data = db.query(
        ReviewTopic.topic_name,
        ReviewTopic.topic_sentiment,
        func.count(ReviewTopic.feedback_id)
    ).filter(ReviewTopic.branch_id == branch_id).group_by(ReviewTopic.topic_name, ReviewTopic.topic_sentiment).all()

    for topic_name, sentiment, count in topic_data:
        if topic_name not in topic_sentiment:
            topic_sentiment[topic_name] = {"positive": 0, "negative": 0, "mixed": 0, "neutral": 0}
        topic_sentiment[topic_name][sentiment] += round((count / total_reviews) * 100) if total_reviews else 0

    #logging.info(f"Topic sentiment: {topic_sentiment}")

    emotion_data = db.query(
        Emotion.emotions, func.count(Emotion.emotions)
    ).filter(Emotion.branch_id == branch_id).group_by(Emotion.emotions).all()

    emotion_count = {emotion: count for emotion, count in emotion_data}
    #logging.info(f"Emotion count: {emotion_count}")

    word_data = db.query(
        Word.words, Word.sentiment, func.count(Word.words)
    ).filter(Word.branch_id == branch_id).group_by(Word.words, Word.sentiment).all()

    words_sentiment = {}
    for word, sentiment, count in word_data:
        if word not in words_sentiment:
            words_sentiment[word] = {"positive": 0, "negative": 0, "mixed": 0, "neutral": 0}
        words_sentiment[word][sentiment] += round((count / total_reviews) * 100) if total_reviews else 0

    #logging.info(f"Words sentiment: {words_sentiment}")

    sentiment_breakdown_percent = {
        key: round((value / total_reviews) * 100) if total_reviews else 0 for key, value in sentiment_breakdown.items()
    }
    #logging.info(f"Sentiment breakdown (percentage): {sentiment_breakdown_percent}")

    return {
        "overall_sentiment_score": overall_sentiment_score,
        "topic_sentiment": topic_sentiment,
        "emotion_count": emotion_count,
        "words_sentiment": words_sentiment,
        "sentiment_breakdown": sentiment_breakdown_percent,
        "total_reviews": total_reviews
    }



def generate_feedback_recommendations(db: Session, branch_id: int):
    """
    Generate recommendations based on aggregated feedback and store them in the database.
    """
    aggregated_feedback = generate_aggregated_feedback(db, branch_id)

    #logging.info(f"\n========== 📢 AGGREGATED FEEDBACK FOR BRANCH {branch_id} ==========")
    #logging.info(f"Aggregated Feedback: {aggregated_feedback}")
    #logging.info("===============================================================\n")

    recommendation_response = rec_agent.generate_recommendations(aggregated_feedback)

    stored_recommendations = []

    try:
        for rec in recommendation_response.recommendations:
            new_recommendation = Recommendation(
                recommendation=rec.recommendation,
                topic=rec.topic,
                severity=rec.severity,
                rank=rec.rank,
                branch_id=branch_id
            )
            db.add(new_recommendation)
            stored_recommendations.append(new_recommendation)

        db.commit()
        #logging.info(f"Inserted {len(stored_recommendations)} recommendations for branch_id: {branch_id}")
        #return stored_recommendations  # Return the full list if needed

    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail={
                "status": False,
                "message": "Failed to store recommendations",
                "error": str(e),
            }
        )
