import logging
import math
from . import rapid_api  # Asegúrate de que el módulo esté configurado correctamente

# Configura el logger
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)  # Cambia a INFO o WARNING en producción


class ReviewAnalyzer:
    def __init__(self, asin):
        self.asin = asin
        self.total_reviews = 0
        self.stars = {}
        self.muestras_por_estrella = {}
        self.best_reviews = []
        self.worst_reviews = []
        logger.info(f"ReviewAnalyzer initialized for ASIN: {asin}")

    def fetch_reviews_data(self):
        try:
            logger.info(f"Fetching reviews data for ASIN: {self.asin}")
            data_from_api = rapid_api.getProductReviews(self.asin, 1, 'US', 'ALL', 'TOP_REVIEWS')
            self.total_reviews = data_from_api['data']['total_reviews']
            logger.debug(f"Total reviews: {self.total_reviews}")

            productDetails = rapid_api.getProductDetails(self.asin, 'US')
            logger.debug(f"Product details raw data: {productDetails}")

            # Manejar la ausencia de distribución de calificaciones
            if 'rating_distribution' in productDetails['data']:
                self.stars = productDetails['data']['rating_distribution']
                logger.info(f"Rating distribution: {self.stars}")
            else:
                logger.warning("No rating distribution found. Generating default distribution.")
                # Crear una distribución de calificaciones predeterminada si no existe
                self.stars = {
                    '5': '20%',  # Distribucion predeterminada
                    '4': '20%',
                    '3': '20%',
                    '2': '20%',
                    '1': '20%'
                }

            return True  # Indica que la recolección de datos fue exitosa
        except Exception as e:
            logger.error(f"Error fetching reviews data: {e}", exc_info=True)
            return False  # Indica que hubo un problema

    def calculate_sample(self):
        logger.info("Calculating review sample size")

        # Si no hay reviews totales, usar un valor predeterminado
        if self.total_reviews == 0:
            self.total_reviews = 100  # Valor predeterminado

        muestra = self.calcular_muestra(self.total_reviews)
        logger.debug(f"Calculated sample size: {muestra}")

        nombre_estrella_mapping = {
            "5": "5_STARS",
            "4": "4_STARS",
            "3": "3_STARS",
            "2": "2_STARS",
            "1": "1_STARS"
        }

        for star, percentage in self.stars.items():
            try:
                nombre_estrella = nombre_estrella_mapping.get(star, "")
                porcentaje_decimal = float(percentage.strip('%')) / 100
                muestras_estrella = max(1, round(muestra * porcentaje_decimal))  # Asegurar al menos 1 muestra
                self.muestras_por_estrella[nombre_estrella] = muestras_estrella
                logger.debug(f"Star: {star}, Percentage: {percentage}, Sample: {muestras_estrella}")
            except Exception as e:
                logger.error(f"Error processing star data: {star}, percentage: {percentage}", exc_info=True)

    def filter_reviews(self):
        logger.info("Filtering reviews based on calculated samples")

        # Si no hay muestras por estrella, generar muestras predeterminadas
        if not self.muestras_por_estrella:
            logger.warning("No samples per star. Generating default samples.")
            self.muestras_por_estrella = {
                '5_STARS': 1,
                '4_STARS': 1,
                '1_STARS': 1,
                '2_STARS': 1
            }

        # Eliminar muestras de 3 estrellas si es necesario
        if '3_STARS' in self.muestras_por_estrella:
            del self.muestras_por_estrella['3_STARS']

        for estrella, muestras in self.muestras_por_estrella.items():
            try:
                logger.info(f"Fetching reviews for star: {estrella}")

                # Ajustar número de páginas si es necesario
                paginas = max(1, (muestras if muestras >= 10 else 10) // 10 + 1)

                for pagina in range(1, paginas + 1):
                    try:
                        data = rapid_api.getProductReviews(self.asin, str(pagina), "US", estrella, "TOP_REVIEWS")

                        # Validar la existencia de reviews
                        if 'data' in data and 'reviews' in data['data']:
                            reviews = data['data']['reviews']

                            for review in reviews:
                                if estrella in ['5_STARS', '4_STARS']:
                                    self.best_reviews.append(review.get('review_comment', 'Sin comentario'))
                                elif estrella in ['1_STARS', '2_STARS']:
                                    self.worst_reviews.append(review.get('review_comment', 'Sin comentario'))

                            logger.debug(f"Collected {len(reviews)} reviews for {estrella}")
                        else:
                            logger.warning(f"No reviews found for star: {estrella}, page: {pagina}")

                    except Exception as e:
                        logger.error(f"Error fetching reviews for star: {estrella}, page: {pagina}: {e}")

            except Exception as e:
                logger.error(f"Error in review filtering for {estrella}: {e}")

        # Si no hay reviews, agregar comentarios predeterminados
        if not self.best_reviews:
            self.best_reviews = ["No se encontraron reseñas positivas"]
        if not self.worst_reviews:
            self.worst_reviews = ["No se encontraron reseñas negativas"]

    def calcular_muestra(self, N):
        margen_error = 0.05
        Z = 1.96
        p = 0.5
        n = (N * Z ** 2 * p * (1 - p)) / ((N - 1) * margen_error ** 2 + Z ** 2 * p * (1 - p))
        return math.ceil(n)

    def analyze_reviews(self):
        logger.info(f"Starting review analysis for ASIN: {self.asin}")

        # Intentar obtener datos de reviews, continuar incluso si falla
        try:
            self.fetch_reviews_data()
        except Exception as e:
            logger.error(f"Error fetching reviews data: {e}")

        # Calcular muestra, manejar caso de error
        try:
            self.calculate_sample()
        except Exception as e:
            logger.error(f"Error calculating sample: {e}")
            # Usar valores predeterminados si falla
            self.total_reviews = 100
            self.stars = {'5': '20%', '4': '20%', '3': '20%', '2': '20%', '1': '20%'}

        # Filtrar reviews, manejar caso de error
        try:
            self.filter_reviews()
        except Exception as e:
            logger.error(f"Error filtering reviews: {e}")
            # Usar comentarios predeterminados si falla
            self.best_reviews = ["No se encontraron reseñas positivas"]
            self.worst_reviews = ["No se encontraron reseñas negativas"]

        logger.info(
            f"Review analysis completed: {len(self.best_reviews)} best reviews, {len(self.worst_reviews)} worst reviews")

        return self.best_reviews, self.worst_reviews
