#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re
import os

# Ruta del archivo
file_path = 'app/services/tariff_detector.py'

# Leer el contenido actual
with open(file_path, 'r', encoding='utf-8') as file:
    content = file.read()

# 2. Implementar el método _extract_power_and_prices para mejorar la detección de potencia contratada
method_to_add = """
    def _extract_power_and_prices(self):
        \"\"\"Método especializado para extraer potencia contratada y precios de energía/potencia.
        Implementa una búsqueda exhaustiva con patrones mejorados para facturas españolas.\"\"\"
        logging.info("Iniciando extracción de potencia contratada y precios")
        
        # 1. Extraer potencia contratada con múltiples patrones
        if not self.contracted_power:
            power_match = None
            for pattern in [self.CONTRACTED_POWER_PATTERN, self.ALT_CONTRACTED_POWER_PATTERN]:
                power_match = re.search(pattern, self.text, re.IGNORECASE)
                if power_match:
                    try:
                        value = power_match.group(1).replace(',', '.').strip()
                        self.contracted_power = float(value)
                        logging.info(f"Potencia contratada detectada: {self.contracted_power} kW")
                        break
                    except (ValueError, IndexError) as e:
                        logging.warning(f"Error al convertir potencia contratada: {e}")
            
            # Si no se encontró con los patrones principales, buscar usando patrones específicos por periodo
            if not self.contracted_power:
                logging.info("Intentando detectar potencia contratada por periodos")
                total_power = 0
                power_count = 0
                
                for period, pattern in self.POWER_PATTERNS.items():
                    power_match = pattern.search(self.text)
                    if power_match:
                        try:
                            value = float(power_match.group(1).replace(',', '.').strip())
                            self.power_by_period[period] = value
                            total_power += value
                            power_count += 1
                            logging.info(f"Potencia {period} detectada: {value} kW")
                        except (ValueError, IndexError) as e:
                            logging.warning(f"Error al convertir potencia para {period}: {e}")
                
                # Si se encontraron potencias por periodo, calcular el total o promedio
                if power_count > 0:
                    # Para algunas tarifas la potencia contratada es la suma, para otras es igual en todos los periodos
                    # Como heurística, si son muy similares usar una, si hay variación usar la suma
                    values = list(self.power_by_period.values())
                    if values and max(values) - min(values) < 0.1:
                        # Si son casi iguales, usar el primer valor
                        self.contracted_power = values[0]
                        logging.info(f"Potencia contratada inferida (igual en periodos): {self.contracted_power} kW")
                    else:
                        # Si hay diferencias, usar la suma
                        self.contracted_power = total_power
                        logging.info(f"Potencia contratada inferida (suma de periodos): {self.contracted_power} kW")
        
        # 2. Extraer precios de energía por periodo
        logging.info("Detectando precios de energía por periodos")
        for period, pattern in self.ENERGY_PRICE_PATTERNS.items():
            price_match = pattern.search(self.text)
            if price_match:
                try:
                    price = float(price_match.group(1).replace(',', '.').strip())
                    self.energy_prices[period] = price
                    logging.info(f"Precio de energía para {period} detectado: {price} €/kWh")
                except (ValueError, IndexError) as e:
                    logging.warning(f"Error al convertir precio de energía para {period}: {e}")
        
        # Si no se encontró ningún precio por periodo, intentar con precio genérico
        if not any(self.energy_prices.values()):
            logging.info("Intentando detectar precio de energía genérico")
            generic_price_match = re.search(self.GENERIC_ENERGY_PRICE_PATTERN, self.text, re.IGNORECASE)
            if generic_price_match:
                try:
                    price = float(generic_price_match.group(1).replace(',', '.').strip())
                    # Aplicar el mismo precio a todos los periodos
                    for period in ['P1', 'P2', 'P3']:
                        self.energy_prices[period] = price
                    logging.info(f"Precio genérico detectado y aplicado a todos los periodos: {price} €/kWh")
                except (ValueError, IndexError) as e:
                    logging.warning(f"Error al convertir precio genérico: {e}")
                    
        # 3. Extraer precios de potencia
        logging.info("Detectando precios de potencia por periodos")
        for period, pattern in self.POWER_PRICE_PATTERNS.items():
            power_price_match = pattern.search(self.text)
            if power_price_match:
                try:
                    price = float(power_price_match.group(1).replace(',', '.').strip())
                    self.power_prices[period] = price
                    logging.info(f"Precio de potencia para {period} detectado: {price} €/kW")
                except (ValueError, IndexError) as e:
                    logging.warning(f"Error al convertir precio de potencia para {period}: {e}")
"""

# Añadir el método _extract_power_and_prices antes del método _extract_consumos_optimizado
content = re.sub(
    r'(def _extract_consumos_optimizado\(self\):)',
    f'{method_to_add}\n    \\1',
    content
)

# 3. Mejorar la extracción del nombre del cliente con el nuevo patrón
improved_client_extraction = """
        # Extracción del nombre del cliente con múltiples patrones mejorados
        client_name_match = re.search(self.CLIENT_NAME_PATTERN, self.text, re.IGNORECASE)
        
        if client_name_match:
            client_name = client_name_match.group(1).strip()
            # Verificar que no es "Del contrato:" u otro texto no deseado
            if not re.search(r'(?:Del\\s+contrato|N\\.?\\s*Contrato|Num\\.?\\s*Contrato|D?N?I|IBAN)', client_name, re.IGNORECASE):
                self.client_name = client_name
                logging.info(f"Nombre de cliente detectado: {self.client_name}")
            else:
                logging.warning(f"Se detectó un falso positivo como nombre de cliente: {client_name}")
                # Intentar con patrón alternativo
                alt_client_match = re.search(self.ALT_CLIENT_NAME_PATTERN, self.text, re.IGNORECASE)
                if alt_client_match:
                    self.client_name = alt_client_match.group(1).strip()
                    logging.info(f"Nombre de cliente detectado (patrón alternativo): {self.client_name}")
        else:
            # Intentar con patrón alternativo si el principal falló
            alt_client_match = re.search(self.ALT_CLIENT_NAME_PATTERN, self.text, re.IGNORECASE)
            if alt_client_match:
                self.client_name = alt_client_match.group(1).strip()
                logging.info(f"Nombre de cliente detectado (patrón alternativo): {self.client_name}")
            else:
                # Intentar con un tercer patrón adicional
                extra_client_match = re.search(self.EXTRA_CLIENT_NAME_PATTERN, self.text, re.IGNORECASE)
                if extra_client_match:
                    self.client_name = extra_client_match.group(1).strip()
                    logging.info(f"Nombre de cliente detectado (patrón adicional): {self.client_name}")
                else:
                    logging.warning("No se pudo detectar el nombre del cliente")
                    
        # Si se detectó un nombre de cliente, aplicar filtros adicionales para limpieza
        if self.client_name:
            # Eliminar texto no deseado como códigos, fechas, etc.
            self.client_name = re.sub(r'\\b(?:Código|Cód|Ref|Núm|N\\.)\\b.*$', '', self.client_name).strip()
            # Eliminar direcciones de correo si se capturaron por error
            self.client_name = re.sub(r'\\S+@\\S+', '', self.client_name).strip()
            # Eliminar caracteres no alfabéticos al inicio y final
            self.client_name = re.sub(r'^[^A-Za-zÀ-ÿ]+|[^A-Za-zÀ-ÿ]+$', '', self.client_name).strip()
            logging.info(f"Nombre de cliente limpiado: {self.client_name}")
"""

# Reemplazar la sección de extracción del nombre del cliente
content = re.sub(
    r'# Extracción del nombre del cliente.*?(?=# Extracción de la dirección de suministro)',
    improved_client_extraction,
    content,
    flags=re.DOTALL
)

# 4. Mejorar el cálculo de los días de facturación
improved_billing_days = """
            # Calcular días de facturación con múltiples formatos
            try:
                # Intentar varios formatos comunes en facturas españolas
                formats_to_try = ['%d/%m/%Y', '%d-%m-%Y', '%Y-%m-%d', '%d/%m/%y', '%d-%m-%y']
                start_date = None
                end_date = None
                
                for date_format in formats_to_try:
                    try:
                        start_date = datetime.strptime(self.billing_start_date, date_format)
                        break
                    except (ValueError, TypeError):
                        continue
                        
                if not start_date:
                    logging.error(f"No se pudo parsear la fecha inicial: {self.billing_start_date}")
                    return
                
                for date_format in formats_to_try:
                    try:
                        end_date = datetime.strptime(self.billing_end_date, date_format)
                        break
                    except (ValueError, TypeError):
                        continue
                
                if not end_date:
                    logging.error(f"No se pudo parsear la fecha final: {self.billing_end_date}")
                    return
                
                delta = end_date - start_date
                self.billing_days = delta.days + 1  # +1 porque el periodo incluye ambas fechas
                
                if self.billing_days <= 0:
                    logging.warning(f"Error en cálculo de días: inicio {start_date}, fin {end_date}, resultado {self.billing_days}")
                    # Intentar invertir las fechas si hay un error
                    delta = start_date - end_date
                    self.billing_days = delta.days + 1
                
                logging.info(f"Días de facturación calculados: {self.billing_days}")
                
            except Exception as e:
                logging.error(f"Error en cálculo de días de facturación: {e}")
"""

# Reemplazar la sección de cálculo de días de facturación
content = re.sub(
    r'# Calcular días de facturación.*?except Exception as e:.*?logging\.error.*?\)',
    improved_billing_days,
    content,
    flags=re.DOTALL
)

# 5. Añadir la llamada al nuevo método en process_text
process_text_improvement = """
        # Extracción de tramos de potencia, precios y consumos
        if self.detected_tariff:
            tariff_structure = TariffDetector.get_tariff_periods(self.detected_tariff)
        else:
            # Si no se detectó tarifa, usar 2.0TD por defecto
            logging.warning("Usando estructura 2.0TD por defecto para extracción de consumos")
            tariff_structure = TariffDetector.get_tariff_periods('2.0TD')
        
        # Extraer potencias contratadas y precios con el método especializado
        logging.info("Iniciando extracción especializada de potencias y precios")
        self._extract_power_and_prices()
        
        # Extraer consumos con el método optimizado
        self._extract_consumos_optimizado()
"""

# Reemplazar la sección correspondiente en process_text
content = re.sub(
    r'# Extracción de tramos de potencia, precios y consumos.*?self\._extract_consumos_optimizado\(\)',
    process_text_improvement,
    content,
    flags=re.DOTALL
)

# Guardar los cambios
with open(file_path, 'w', encoding='utf-8') as file:
    file.write(content)

print("Mejoras implementadas correctamente en el archivo tariff_detector.py")
