"""
Standardized success marker service for all stages.

Provides consistent success marker creation with standardized JSON format
and behavior across Generate, K8s, Metadata, and other stages.
"""

import json
from datetime import datetime
from typing import Dict, Any, Optional, List
from pathlib import Path

from botocore.exceptions import ClientError
from src.log_context import get_logger


class SuccessMarkerService:
    """
    Standardized service for creating and managing stage success markers.
    
    Ensures consistent behavior and format across all stages:
    - Standardized JSON format with required and optional fields
    - Consistent S3 path structure: czbillgen/datasets/{dataset}/{stage}/_SUCCESS
    - Validation summary inclusion for quality assurance
    - Processing metadata for debugging and analysis
    """
    
    def __init__(self, s3_service):
        """
        Initialize success marker service.
        
        Args:
            s3_service: S3 data service instance for file operations
        """
        self.s3_service = s3_service
        self.logger = get_logger(__name__)
    
    def create_success_marker(
        self,
        dataset_name: str,
        stage: str,
        processing_summary: Optional[Dict[str, Any]] = None,
        config: Optional[Dict[str, Any]] = None,
        validation_summary: Optional[Dict[str, Any]] = None,
        additional_metadata: Optional[Dict[str, Any]] = None
    ) -> bool:
        """
        Create standardized success marker for a stage.
        
        Args:
            dataset_name: Dataset name
            stage: Stage name (generate, k8s, metadata, etc.)
            processing_summary: Summary of processing results
            config: Stage configuration used
            validation_summary: Validation results summary
            additional_metadata: Stage-specific additional metadata
            
        Returns:
            True if successful, False otherwise
        """
        # Create standardized success marker content
        success_content = self._create_standard_format(
            dataset_name=dataset_name,
            stage=stage,
            processing_summary=processing_summary,
            config=config,
            validation_summary=validation_summary,
            additional_metadata=additional_metadata
        )
        
        # Write to S3 using standard path
        success_path = f"czbillgen/datasets/{dataset_name}/{stage}/_SUCCESS"
        
        # Write JSON content to temporary file and upload
        import tempfile
        import os
        
        with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as tmp_file:
            json.dump(success_content, tmp_file, indent=2, default=str)
            tmp_path = tmp_file.name
        
        try:
            self.s3_service.upload_file(tmp_path, success_path)
            
            self.logger.info(
                "Success marker created",
                dataset_name=dataset_name,
                stage=stage,
                path=success_path
            )
            return True
            
        finally:
            # Clean up temp file
            if os.path.exists(tmp_path):
                os.unlink(tmp_path)
    
    def _create_standard_format(
        self,
        dataset_name: str,
        stage: str,
        processing_summary: Optional[Dict[str, Any]] = None,
        config: Optional[Dict[str, Any]] = None,
        validation_summary: Optional[Dict[str, Any]] = None,
        additional_metadata: Optional[Dict[str, Any]] = None
    ) -> Dict[str, Any]:
        """
        Create standardized success marker format.
        
        Standard format includes:
        - status: Always "SUCCESS" 
        - stage: Stage name for identification
        - completed_at: ISO timestamp
        - dataset_name: Dataset identifier
        - processing_summary: Processing metrics and results
        - validation_summary: Validation results (if applicable)
        - config: Stage configuration used
        - metadata: Additional stage-specific information
        - version: Format version for future compatibility
        
        Args:
            dataset_name: Dataset name
            stage: Stage name
            processing_summary: Processing results
            config: Stage configuration
            validation_summary: Validation results
            additional_metadata: Additional metadata
            
        Returns:
            Standardized success marker dictionary
        """
        success_content = {
            # Core required fields
            "status": "SUCCESS",
            "stage": stage,
            "completed_at": datetime.now().isoformat(),
            "dataset_name": dataset_name,
            "version": "1.0",
            
            # Processing information
            "processing_summary": processing_summary or {},
            
            # Validation information (critical for quality assurance)
            "validation_summary": validation_summary or {
                "validation_performed": False,
                "note": "No validation summary provided"
            },
            
            # Configuration used (important for reproducibility)
            "config": config or {},
            
            # Additional stage-specific metadata
            "metadata": additional_metadata or {}
        }
        
        return success_content
    
    def read_success_marker(self, dataset_name: str, stage: str) -> Optional[Dict[str, Any]]:
        """
        Read and parse success marker for a stage.
        
        Args:
            dataset_name: Dataset name
            stage: Stage name
            
        Returns:
            Success marker content as dictionary, or None if not found
        """
        success_path = f"czbillgen/datasets/{dataset_name}/{stage}/_SUCCESS"
        
        # Try to download and parse as JSON
        response = self.s3_service.s3_client.get_object(
            Bucket=self.s3_service.bucket,
            Key=success_path
        )
        
        content = response['Body'].read().decode('utf-8')
        
        # Try to parse as JSON first (new format)
        try:
            return json.loads(content)
        except json.JSONDecodeError:
            # Legacy format - return as text content
            return {
                "status": "SUCCESS",
                "stage": stage,
                "dataset_name": dataset_name,
                "legacy_content": content,
                "format": "legacy"
            }
    
    def check_success_marker_exists(self, dataset_name: str, stage: str) -> bool:
        """
        Check if success marker exists for a stage.
        
        Args:
            dataset_name: Dataset name
            stage: Stage name
            
        Returns:
            True if success marker exists, False otherwise
        """
        success_path = f"czbillgen/datasets/{dataset_name}/{stage}/_SUCCESS"
        try:
            self.s3_service.s3_client.head_object(
                Bucket=self.s3_service.bucket,
                Key=success_path
            )
            return True
        except ClientError as e:
            if e.response['Error']['Code'] == '404':
                return False
            else:
                raise
    
    def delete_success_marker(self, dataset_name: str, stage: str) -> bool:
        """
        Delete success marker for a stage.
        
        Used by --force operations to clear success state.
        
        Args:
            dataset_name: Dataset name
            stage: Stage name
            
        Returns:
            True if successful or marker didn't exist, False on error
        """
        success_path = f"czbillgen/datasets/{dataset_name}/{stage}/_SUCCESS"
        
        # Check if it exists first - fail fast if it doesn't exist
        if not self.check_success_marker_exists(dataset_name, stage):
            return True  # Already doesn't exist
        
        # Delete the marker
        self.s3_service.s3_client.delete_object(
            Bucket=self.s3_service.bucket,
            Key=success_path
        )
        
        self.logger.info(
            "Success marker deleted",
            dataset_name=dataset_name,
            stage=stage,
            path=success_path
        )
        return True


def create_processing_summary(
    total_items: int,
    processed_items: int,
    failed_items: int,
    input_cost: Optional[float] = None,
    output_cost: Optional[float] = None,
    providers_processed: Optional[List[str]] = None,
    months_processed: Optional[List[str]] = None,
    additional_metrics: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
    """
    Helper function to create standardized processing summary.
    
    Args:
        total_items: Total items to process
        processed_items: Successfully processed items
        failed_items: Failed items
        input_cost: Total input cost (optional)
        output_cost: Total output cost (optional)
        providers_processed: List of providers processed
        months_processed: List of months processed
        additional_metrics: Additional stage-specific metrics
        
    Returns:
        Standardized processing summary dictionary
    """
    summary = {
        "total_items": total_items,
        "processed_items": processed_items,
        "failed_items": failed_items,
        "success_rate": processed_items / total_items if total_items > 0 else 0.0
    }
    
    # Add optional financial metrics
    if input_cost is not None:
        summary["input_cost"] = input_cost
    if output_cost is not None:
        summary["output_cost"] = output_cost
        if input_cost is not None:
            summary["cost_conservation"] = abs(input_cost - output_cost) < 0.01
    
    # Add optional processing scope
    if providers_processed:
        summary["providers_processed"] = providers_processed
    if months_processed:
        summary["months_processed"] = months_processed
    
    # Add additional metrics
    if additional_metrics:
        summary["additional_metrics"] = additional_metrics
    
    return summary


def create_validation_summary(
    validation_performed: bool,
    validation_passed: bool,
    total_validations: int = 0,
    failed_validations: int = 0,
    validation_details: Optional[Dict[str, Any]] = None,
    critical_failures: Optional[List[str]] = None
) -> Dict[str, Any]:
    """
    Helper function to create standardized validation summary.
    
    Args:
        validation_performed: Whether validation was performed
        validation_passed: Whether all validations passed
        total_validations: Total number of validation checks
        failed_validations: Number of failed validation checks
        validation_details: Detailed validation results
        critical_failures: List of critical validation failures
        
    Returns:
        Standardized validation summary dictionary
    """
    summary = {
        "validation_performed": validation_performed,
        "validation_passed": validation_passed
    }
    
    if validation_performed:
        summary.update({
            "total_validations": total_validations,
            "failed_validations": failed_validations,
            "success_rate": (total_validations - failed_validations) / total_validations if total_validations > 0 else 0.0
        })
        
        if validation_details:
            summary["validation_details"] = validation_details
            
        if critical_failures:
            summary["critical_failures"] = critical_failures
    
    return summary