"""Sync classification results back to email providers."""
import logging
from typing import List, Dict, Any, Optional
from abc import ABC, abstractmethod

from src.email_providers.base import ClassificationResult, BaseProvider

logger = logging.getLogger(__name__)


class ProviderSync(ABC):
    """Abstract base for syncing results back to providers."""

    @abstractmethod
    def sync_classifications(
        self,
        results: List[ClassificationResult],
        category_to_label: Optional[Dict[str, str]] = None
    ) -> Dict[str, Any]:
        """
        Sync classification results back to provider.

        Args:
            results: Classification results
            category_to_label: Map category names to provider labels

        Returns:
            Sync statistics
        """
        pass


class GmailSync(ProviderSync):
    """Sync results back to Gmail via labels."""

    def __init__(self, provider):
        """Initialize Gmail sync."""
        self.provider = provider

        if not hasattr(provider, 'update_labels'):
            raise ValueError("Provider must support update_labels")

        self.logger = logging.getLogger(__name__)

    def sync_classifications(
        self,
        results: List[ClassificationResult],
        category_to_label: Optional[Dict[str, str]] = None
    ) -> Dict[str, Any]:
        """Sync classifications as Gmail labels."""
        if not category_to_label:
            # Default: use category name as label
            category_to_label = {
                'junk': 'EmailSorter/Junk',
                'transactional': 'EmailSorter/Transactional',
                'auth': 'EmailSorter/Auth',
                'newsletters': 'EmailSorter/Newsletters',
                'social': 'EmailSorter/Social',
                'automated': 'EmailSorter/Automated',
                'conversational': 'EmailSorter/Conversational',
                'work': 'EmailSorter/Work',
                'personal': 'EmailSorter/Personal',
                'finance': 'EmailSorter/Finance',
                'travel': 'EmailSorter/Travel',
                'unknown': 'EmailSorter/Unknown'
            }

        self.logger.info(f"Starting Gmail sync for {len(results)} results")

        # Build batch updates
        updates = []
        synced_count = 0
        failed_count = 0

        for result in results:
            try:
                # Get label for category
                label = category_to_label.get(result.category)

                if not label:
                    self.logger.debug(f"No label mapping for {result.category}")
                    failed_count += 1
                    continue

                updates.append({
                    'email_id': result.email_id,
                    'labels': [label]
                })

                synced_count += 1

            except Exception as e:
                self.logger.warning(f"Error syncing {result.email_id}: {e}")
                failed_count += 1

        # Batch update via provider
        try:
            if updates:
                self.provider.batch_update(updates)
                self.logger.info(f"Synced {synced_count} emails to Gmail")
        except Exception as e:
            self.logger.error(f"Batch update failed: {e}")
            return {
                'provider': 'gmail',
                'synced': synced_count,
                'failed': failed_count + len(results) - synced_count,
                'error': str(e)
            }

        return {
            'provider': 'gmail',
            'synced': synced_count,
            'failed': failed_count,
            'total': len(results)
        }


class IMAPSync(ProviderSync):
    """Sync results back to IMAP server via flags."""

    def __init__(self, provider):
        """Initialize IMAP sync."""
        self.provider = provider

        if not hasattr(provider, 'update_labels'):
            raise ValueError("Provider must support update_labels")

        self.logger = logging.getLogger(__name__)

    def sync_classifications(
        self,
        results: List[ClassificationResult],
        category_to_label: Optional[Dict[str, str]] = None
    ) -> Dict[str, Any]:
        """Sync classifications as IMAP flags/keywords."""
        if not category_to_label:
            # Default: create IMAP keywords
            category_to_label = {
                'junk': '$Junk',
                'transactional': 'EmailSorter-Transactional',
                'auth': 'EmailSorter-Auth',
                'newsletters': 'EmailSorter-Newsletters',
                'work': 'EmailSorter-Work',
                'personal': 'EmailSorter-Personal',
                'finance': 'EmailSorter-Finance',
                'travel': 'EmailSorter-Travel',
            }

        self.logger.info(f"Starting IMAP sync for {len(results)} results")

        # Build batch updates
        updates = []
        synced_count = 0
        failed_count = 0

        for result in results:
            try:
                # Get label for category
                label = category_to_label.get(result.category)

                if not label:
                    self.logger.debug(f"No label mapping for {result.category}")
                    continue

                updates.append({
                    'email_id': result.email_id,
                    'labels': [label]
                })

                synced_count += 1

            except Exception as e:
                self.logger.warning(f"Error syncing {result.email_id}: {e}")
                failed_count += 1

        # Batch update via provider
        try:
            if updates:
                self.provider.batch_update(updates)
                self.logger.info(f"Synced {synced_count} emails to IMAP")
        except Exception as e:
            self.logger.error(f"Batch update failed: {e}")
            return {
                'provider': 'imap',
                'synced': synced_count,
                'failed': failed_count + len(results) - synced_count,
                'error': str(e)
            }

        return {
            'provider': 'imap',
            'synced': synced_count,
            'failed': failed_count,
            'total': len(results)
        }


def get_sync_handler(provider: BaseProvider) -> Optional[ProviderSync]:
    """Get appropriate sync handler for provider."""
    provider_name = getattr(provider, 'name', 'unknown').lower()

    if 'gmail' in provider_name:
        return GmailSync(provider)
    elif 'imap' in provider_name:
        return IMAPSync(provider)
    else:
        logger.warning(f"No sync handler for provider: {provider_name}")
        return None
