import os
import json
import time
import queue
import requests
import logging
from flask import Blueprint, request, Response
from dotenv import load_dotenv

from src.api_consumers.review_analysis import ReviewAnalyzer
from src.helpers.processWords import NgramAnalysis
from src.helpers.processImage import CreateDocumentPPT
from src.api_consumers.openai_client import OpenAIClient
from .sentenceFinder import search
from .imageAnalyzer import analyzePattern
from .asinSourcer import getAsinFromUrl
from .images_url_sourcer import get_images_url
from .proposal_ppt import ProposalPPT
from .proposal_content import ProposalContent

# Configurar logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

load_dotenv()
event_queue = queue.Queue()


def event_handler(message):
    event_queue.put(message)


proposalController = Blueprint('proposalController', __name__)


@proposalController.route('/form-notification', methods=['POST'])
def formReadyNotification():
    logger.info('Received form notification request')

    try:
        data = request.json
        logger.info(f'Request payload: Company Name: {data.get("companyName")}, Token: {data.get("formToken")}')

        # Procesar la notificación y agregarla a la cola de eventos
        event_handler({
            "event": 'form',
            "companyName": data['companyName'],
            "token": data['formToken']
        })

        # Enviar la notificación a otro servicio
        response = requests.post(
            os.getenv('AGENCIA_URL') + 'api/v1/notifications/store',
            headers={'Content-Type': 'application/json'},
            json={
                "type": 'form',
                "companyName": data['companyName'],
                "token": data['formToken']
            }
        )
        logger.info(f'Sent notification to Agencia, response status: {response.status_code}')

        return "Notification Sent!"
    except Exception as e:
        logger.error(f"Error in form notification: {str(e)}")
        return "Error sending notification", 500


@proposalController.route('/proposal', methods=['POST'])
def createProposal():
    logger.info('Received proposal creation request')

    try:
        # Validación inicial de la solicitud
        if not request.json:
            logger.error("No JSON payload in request")
            return {"error": "Request payload must be JSON"}, 400

        data = request.json

        required_fields = [
            "competitorLink", "companyName", "titleKeywords", "formToken",
            "productTitle", "productDescription", "buyerDescription",
            "diffFactor", "competitorsFeatures", "listing_image", "aplus_content"
        ]

        # Validar que los campos obligatorios estén presentes
        missing_fields = [field for field in required_fields if field not in data]
        if missing_fields:
            logger.error(f"Missing required fields: {missing_fields}")
            return {"error": f"Missing required fields: {', '.join(missing_fields)}"}, 400

        logger.info(
            f'Request payload: Competitor Link: {data.get("competitorLink")}, Company Name: {data.get("companyName")}'
        )

        urls = data['competitorLink'].split(',')
        if not urls:
            logger.error("Competitor Link is invalid or empty")
            return {"error": "Competitor Link is invalid or empty"}, 400

        keywords = data['titleKeywords'].split(',')
        proposal_file_name = f"{data['companyName']}_{data['formToken']}"

        logger.info(f"Processing ASIN from URL: {urls[0]}")
        asin = getAsinFromUrl(urls[0])

        logger.info(f"Analyzing reviews for ASIN: {asin}")
        reviewAnalyzer = ReviewAnalyzer(asin)
        try:
            bestReviews, worstReviews = reviewAnalyzer.analyze_reviews()
        except KeyError as e:
            logger.error(f"KeyError during review analysis: {str(e)}")
            return {"error": f"Review data missing key: {str(e)}"}, 400
        except Exception as e:
            logger.error(f"Error during review analysis: {str(e)}")
            return {"error": "Failed to analyze reviews"}, 500

        logger.info(f"Best Reviews: {len(bestReviews)}, Worst Reviews: {len(worstReviews)}")

        # Procesar palabras clave
        try:
            processWords = NgramAnalysis(bestReviews)
            bestMonograms = processWords.extract_common_words_across_all_texts()
            bestBigrams = processWords.extract_common_bigrams_across_all_texts()
            bestTrigrams = processWords.extract_common_trigrams_across_all_texts()
            wordsArray = processWords.extract_words_from_dataFrames((bestBigrams, bestTrigrams), nro=5)

            if worstReviews:
                processWords = NgramAnalysis(worstReviews)
                worstMonograms = processWords.extract_common_words_across_all_texts()
                worstBigrams = processWords.extract_common_bigrams_across_all_texts()
                worstTrigrams = processWords.extract_common_trigrams_across_all_texts()
                logger.info("Worst reviews processed")
        except Exception as e:
            logger.error(f"Error processing reviews or generating word clouds: {str(e)}")
            return {"error": "Error processing reviews or generating word clouds"}, 500

        # Generar WordClouds
        try:
            logger.info("Generating WordClouds")
            processImage = CreateDocumentPPT()
            positiveWordCloud = processImage.add_wordcloud_to_slide(bestMonograms)

            if worstReviews:
                negativeWordCloud = processImage.add_wordcloud_to_slide(worstMonograms)
        except Exception as e:
            logger.error(f"Error generating WordClouds: {str(e)}")
            return {"error": "Failed to generate WordClouds"}, 500

        # Crear contenido de la propuesta
        try:
            logger.info("Generating proposal content")
            proposal_content = ProposalContent(
                OpenAIClient(),
                data['productTitle'],
                data['model'],
                data['set'],
                data['props'],
                data['brandVision'],
                data['brandCreationReason'],
                "Technical" if data['productApproach'] else "Benefit"
            )

            proposal_content.build_general_context(
                data['productTitle'],
                data['productDescription'],
                data['buyerDescription'],
                data['diffFactor'],
                data['competitorsFeatures'],
            )
        except Exception as e:
            logger.error(f"Error generating proposal content: {str(e)}")
            return {"error": "Failed to generate proposal content"}, 500

        # Crear PPT
        try:
            logger.info("Creating Proposal PPT")
            proposal_ppt = ProposalPPT(
                proposal_file_name,
                positiveWordCloud,
                get_images_url(data['productTitle']),
                (bestMonograms, bestBigrams, bestTrigrams),
                negativeWordCloud if 'negativeWordCloud' in locals() else None,
                (worstMonograms, worstBigrams, worstTrigrams) if 'worstMonograms' in locals() else None,
                proposal_content.generate_main_image_text() if int(data['listing_image']) else None,
                proposal_content.generate_main_image() if int(data['listing_image']) else None,
                proposal_content.generate_lifestyle_image_text() if int(data['listing_image']) else None,
                proposal_content.generate_lifestyle_image() if int(data['listing_image']) else None,
                proposal_content.generate_infographic_image_text() if int(data['listing_image']) else None,
                proposal_content.generate_infographic_image() if int(data['listing_image']) else None,
                proposal_content.generate_a_plus_content_text() if data['aplus_content'] != '0' else None,
                proposal_content.generate_listing_video_text() if int(data['listing_video']) else None,
                proposal_content.generate_premium_a_plus_content_text() if data['aplus_content'] != '0' else None,
                proposal_content.generate_premium_a_plus_video_content_text() if data['selected_premium'].find(
                    'video') != -1 else None,
                proposal_content.generate_sponsored_ads_video_text() if int(data['sba_video']) else None,
                proposal_content.generate_brand_story_text() if int(data['brand_story']) else None
            )

            proposal_ppt.generate_ppt()
        except Exception as e:
            logger.error(f"Error creating proposal PPT: {str(e)}")
            return {"error": "Failed to create proposal PPT"}, 500

        # Enviar notificaciones
        try:
            logger.info("Sending proposal notifications to Agencia")
            response_notification = requests.post(
                os.getenv('AGENCIA_URL') + 'api/v1/notifications/store',
                headers={'Content-Type': 'application/json'},
                json={
                    "type": 'proposal',
                    "companyName": data['companyName'],
                    "token": data['formToken']
                }
            )
            logger.info(f'Sent proposal notification, response status: {response_notification.status_code}')

            response_status = requests.post(
                os.getenv('AGENCIA_URL') + 'api/v1/update-proposal-status',
                headers={'Content-Type': 'application/json'},
                json={'token': data['formToken']}
            )
            logger.info(f'Updated proposal status, response status: {response_status.status_code}')
        except requests.RequestException as e:
            logger.error(f"Error sending notifications: {str(e)}")
            return {"error": "Failed to send notifications"}, 500

        logger.info(f"Proposal created successfully for {data['companyName']} with token {data['formToken']}")
        return {"message": "Proposal created successfully"}

    except Exception as e:
        logger.error(f"Unexpected error: {str(e)}")
        return {"error": "An unexpected error occurred", "details": str(e)}, 500


def stream_events():
    try:
        while True:
            # Wait for an event message
            message = event_queue.get(block=False)
            yield f"data: {json.dumps(message)}\n\n"
    except queue.Empty:
        # Send a comment as a heartbeat
        yield ':keepalive\n\n'
    except GeneratorExit:
        logger.info("Stream was closed by the client")


@proposalController.route('/proposal-notification')
def proposalNotification():
    logger.info('Started streaming events')
    return Response(
        stream_events(),
        mimetype='text/event-stream',
        headers={'Cache-Control': 'no-cache'}
    )
