"""
Advanced error logging and validation system for Data Population feature
"""
import logging
import json
from datetime import datetime, timedelta
from typing import Dict, List, Tuple, Optional

class DataPopulationLogger:
    def __init__(self):
        # Set up logging
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler('data_population.log'),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger(__name__)
        self.operation_id = datetime.now().strftime("%Y%m%d_%H%M%S")
        
    def log_operation_start(self, operation_type: str, params: Dict):
        """Log the start of a data population operation"""
        self.logger.info(f"OPERATION_START [{self.operation_id}]: {operation_type}")
        self.logger.info(f"Parameters: {json.dumps(params, default=str)}")
        
    def log_sim_analysis(self, sim_info: Dict, existing_dates: List[str], missing_dates: List[str]):
        """Log analysis of a specific SIM"""
        self.logger.info(f"SIM_ANALYSIS [{self.operation_id}]: {sim_info['sim_number']} ({sim_info['msisdn']})")
        self.logger.info(f"  Existing dates: {existing_dates}")
        self.logger.info(f"  Missing dates to fill: {missing_dates}")
        
    def log_data_validation(self, sim_number: str, date: str, validation_result: bool, reason: str = ""):
        """Log data validation results"""
        status = "PASS" if validation_result else "FAIL"
        self.logger.info(f"VALIDATION [{self.operation_id}]: {sim_number} - {date} - {status} - {reason}")
        
    def log_data_addition(self, sim_number: str, date: str, usage_gb: float, success: bool, error: str = ""):
        """Log data addition attempts"""
        status = "SUCCESS" if success else "FAILED"
        self.logger.info(f"DATA_ADD [{self.operation_id}]: {sim_number} - {date} - {usage_gb}GB - {status}")
        if error:
            self.logger.error(f"ERROR: {error}")
            
    def log_operation_summary(self, total_sims: int, total_additions: int, errors: int):
        """Log operation summary"""
        self.logger.info(f"OPERATION_COMPLETE [{self.operation_id}]: {total_sims} SIMs processed, {total_additions} records added, {errors} errors")

class DataPopulationValidator:
    def __init__(self, cursor, logger: DataPopulationLogger):
        self.cursor = cursor
        self.logger = logger
        
    def get_existing_dates_for_sim(self, msisdn: str) -> List[str]:
        """Get all existing dates for a SIM"""
        try:
            self.cursor.execute("""
                SELECT DISTINCT date_from, date_to, daily_breakdown 
                FROM usage_records 
                WHERE msisdn = %s 
                ORDER BY date_from
            """, (msisdn,))
            
            records = self.cursor.fetchall()
            existing_dates = set()
            
            for record in records:
                # Add all dates in the range
                current_date = record['date_from']
                end_date = record['date_to']
                
                while current_date <= end_date:
                    existing_dates.add(current_date.strftime('%Y-%m-%d'))
                    current_date += timedelta(days=1)
                
                # Also check daily_breakdown if it exists
                if record['daily_breakdown']:
                    try:
                        breakdown = json.loads(record['daily_breakdown'])
                        for date_str in breakdown.keys():
                            existing_dates.add(date_str)
                    except:
                        pass
                        
            return sorted(list(existing_dates))
            
        except Exception as e:
            self.logger.log_data_validation(msisdn, "ALL", False, f"Error getting existing dates: {str(e)}")
            return []
    
    def validate_date_available(self, msisdn: str, target_date: str) -> Tuple[bool, str]:
        """Validate that a date is available for data addition"""
        try:
            # Check if this exact date already has data
            self.cursor.execute("""
                SELECT COUNT(*) as count FROM usage_records 
                WHERE msisdn = %s AND (
                    (date_from <= %s AND date_to >= %s) OR
                    (daily_breakdown::jsonb ? %s)
                )
            """, (msisdn, target_date, target_date, target_date))
            
            result = self.cursor.fetchone()
            count = result['count'] if result else 0
            
            if count > 0:
                return False, f"Date {target_date} already has data for MSISDN {msisdn}"
            
            return True, "Date available"
            
        except Exception as e:
            return False, f"Validation error: {str(e)}"
    
    def get_safe_date_range(self, msisdn: str, days_to_add: int) -> Tuple[str, str, List[str]]:
        """Get a safe date range that doesn't conflict with existing data"""
        existing_dates = self.get_existing_dates_for_sim(msisdn)
        
        if not existing_dates:
            # No existing data, start from a reasonable date
            end_date = datetime.now().date()
            start_date = end_date - timedelta(days=days_to_add - 1)
            return start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'), []
        
        # Find the latest existing date
        latest_date = datetime.strptime(max(existing_dates), '%Y-%m-%d').date()
        
        # Start adding data from the day after the latest existing date
        start_date = latest_date + timedelta(days=1)
        end_date = start_date + timedelta(days=days_to_add - 1)
        
        # Generate the list of dates to add
        dates_to_add = []
        current_date = start_date
        while current_date <= end_date:
            date_str = current_date.strftime('%Y-%m-%d')
            is_available, reason = self.validate_date_available(msisdn, date_str)
            if is_available:
                dates_to_add.append(date_str)
            else:
                self.logger.log_data_validation(msisdn, date_str, False, reason)
            current_date += timedelta(days=1)
        
        return start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'), dates_to_add