import logging
from datetime import datetime
from typing import List, Dict, Optional, Any
from sqlalchemy.orm import Session
from src.apps.wine_match.services.matcher_service import execute
from sqlalchemy.orm import Session
from src.core.dependencies import get_db
from src.apps.match.enums import MatchedType, Status
from src.apps.wine_match.services.output_service import is_valid_crawl_output

logger = logging.getLogger(__name__)

async def execute_wine_match_job(
    db: Session, 
    codes: List[str], 
    run_keywords: List[bool], 
    dates: List[Optional[datetime]], 
    output_service: Optional[Dict[str, str]] = None, 
    matcher_service=None, 
    logs_service=None
) -> Dict[str, Any]:
    """
    Execute wine match job - Python version of the Groovy WineMatchJob.execute
    
    Args:
        db: Database session
        codes: List of retailer codes
        run_keywords: List of booleans indicating whether to run keyword matching
        dates: List of dates for crawl outputs
        output_service: Service for validating output files
        matcher_service: Service for matching
        logs_service: Service for logging matches
        
    Returns:
        Dict: Result summary
    """
    start_time = datetime.now()
    today = datetime.now()
    
    results = {
        'successful': [],
        'failed': [],
        'start_time': start_time.isoformat(),
        'end_time': None,
        'total_count': len(codes) if codes else 0
    }
    
    if not codes:
        logger.warning("No codes provided for wine match job")
        results['end_time'] = datetime.now().isoformat()
        results['duration_seconds'] = (datetime.now() - start_time).total_seconds()
        return results
    
    # Process each code
    for i, code in enumerate(codes):
        if i >= len(codes) or i >= len(run_keywords) or i >= len(dates):
            break
            
        date = dates[i]
        is_keyword = run_keywords[i]
        
        # try:
        # Check if output is valid
        if is_valid_crawl_output(code, date):
            # Execute matcher
            execute_matcher(code, is_keyword, date)
            
            results['successful'].append(code)
            logger.info(f"Successfully processed code {code}")
        else:
            date_str = date.strftime('%Y-%m-%d') if date else "null"
            logger.warning(f"[{code}] match input not found at: {date_str}")
            results['failed'].append(code)
        # except Exception as e:
        #     logger.error(f"Error processing code {code}: {str(e)}")
        #     results['failed'].append(code)
    
    # Calculate execution time
    end_time = datetime.now()
    duration = (end_time - start_time).total_seconds()
    
    logger.info(f"Wine Match Job completed. Execution time: {duration} seconds")
    
    results['end_time'] = end_time.isoformat()
    results['duration_seconds'] = duration
    
    return results


# Function to execute matcher service
def execute_matcher(code: str, run_keyword: bool, date: Optional[datetime] = None):
    """
    Execute the matcher service for the given code
    
    Args:
        code: The retailer code
        run_keyword: Whether to run keyword matching
        date: The date to use for matching (defaults to current date)
    """
    
    # Get database session
    db = next(get_db())
    # try:
    logger.info(f"Executing matcher for {code}, keyword={run_keyword}")
    execute(db, code, run_keyword, date)
    # except Exception as e:
    #     logger.error(f"Error executing matcher: {str(e)}")
    #     raise
    # finally:
    #     db.close()

async def trigger_wine_match_job(
    db: Session, 
    codes: List[str], 
    run_keywords: List[bool], 
    dates: List[Optional[datetime]],
    mode: Optional[str] = None
) -> Dict[str, Any]:
    """
    Trigger the wine match job with the given parameters
    
    Args:
        db: Database session
        codes: List of retailer codes
        run_keywords: List of boolean flags indicating whether to run keyword matching
        dates: List of dates for crawl outputs
        mode: Operation mode
        
    Returns:
        Dict: Result of job trigger operation
    """
    try:
        # Execute the job
        result = await execute_wine_match_job(db, codes, run_keywords, dates)
        
        return {
            'status': 'completed',
            'job_id': f"wine-match-{datetime.now().timestamp()}",
            'mode': mode,
            'results': result
        }
    except Exception as e:
        logger.error(f"Error triggering wine match job: {str(e)}")
        raise e
