"""
Gmail Integration Service
Handles voice-controlled email operations
"""
import requests
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from typing import List, Dict, Optional
import logging

logger = logging.getLogger(__name__)


class GmailService:
    """Service for Gmail API operations"""

    API_BASE = "https://www.googleapis.com/gmail/v1/users"

    def __init__(self, access_token: str, refresh_token: str = None):
        self.access_token = access_token
        self.refresh_token = refresh_token

    def _get_headers(self) -> Dict:
        """Get headers with authentication"""
        return {
            'Authorization': f'Bearer {self.access_token}',
            'Content-Type': 'application/json'
        }

    def _decode_body(self, data: str) -> str:
        """Decode base64url encoded email body"""
        # Add padding if needed
        padding = 4 - len(data) % 4
        if padding != 4:
            data += '=' * padding

        try:
            return base64.urlsafe_b64decode(data).decode('utf-8')
        except:
            return data

    def get_messages(self, label_ids: List[str] = None,
                    max_results: int = 10,
                    query: str = None) -> Dict:
        """Get list of messages"""

        params = {'maxResults': max_results}

        if label_ids:
            params['labelIds'] = label_ids

        if query:
            params['q'] = query

        try:
            response = requests.get(
                f"{self.API_BASE}/me/messages",
                headers=self._get_headers(),
                params=params
            )

            if response.status_code == 200:
                return response.json()
            elif response.status_code == 401:
                return {'error': 'token_expired'}
            else:
                return {'error': response.text}

        except Exception as e:
            logger.error(f"Failed to get messages: {e}")
            return {'error': str(e)}

    def get_message(self, message_id: str,
                    format: str = 'metadata',
                    metadata_headers: List[str] = None) -> Dict:
        """Get full message details"""

        params = {'format': format}

        if metadata_headers:
            params['metadataHeaders'] = metadata_headers

        try:
            response = requests.get(
                f"{self.API_BASE}/me/messages/{message_id}",
                headers=self._get_headers(),
                params=params
            )

            if response.status_code == 200:
                return response.json()
            else:
                return {'error': response.text}

        except Exception as e:
            logger.error(f"Failed to get message: {e}")
            return {'error': str(e)}

    def send_message(self, to: str,
                    subject: str,
                    body: str,
                    is_html: bool = False,
                    thread_id: str = None) -> Dict:
        """Send a new email or reply"""

        # Create message
        if is_html:
            message = MIMEText(body, 'html')
        else:
            message = MIMEText(body)

        message['to'] = to
        message['subject'] = subject

        raw = base64.urlsafe_b64encode(message.as_bytes()).decode()

        params = {}
        url = f"{self.API_BASE}/me/messages/send"

        if thread_id:
            params['threadId'] = thread_id

        try:
            response = requests.post(
                url,
                headers=self._get_headers(),
                params=params,
                json={'raw': raw}
            )

            if response.status_code in [200, 201]:
                return response.json()
            else:
                return {'error': response.text}

        except Exception as e:
            logger.error(f"Failed to send message: {e}")
            return {'error': str(e)}

    def draft_message(self, to: str,
                     subject: str,
                     body: str) -> Dict:
        """Create a draft message"""

        message = MIMEText(body)
        message['to'] = to
        message['subject'] = subject

        raw = base64.urlsafe_b64encode(message.as_bytes()).decode()

        try:
            response = requests.post(
                f"{self.API_BASE}/me/drafts",
                headers=self._get_headers(),
                json={'message': {'raw': raw}}
            )

            if response.status_code in [200, 201]:
                return response.json()
            else:
                return {'error': response.text}

        except Exception as e:
            logger.error(f"Failed to create draft: {e}")
            return {'error': str(e)}

    def get_unread_count(self) -> int:
        """Get count of unread messages"""

        try:
            response = requests.get(
                f"{self.API_BASE}/me/messages",
                headers=self._get_headers(),
                params={'labelIds': ['UNREAD'], 'maxResults': 0}
            )

            if response.status_code == 200:
                return response.json().get('resultSizeEstimate', 0)
            return 0

        except Exception as e:
            logger.error(f"Failed to get unread count: {e}")
            return 0

    def get_inbox_summary(self, max_results: int = 5) -> List[Dict]:
        """Get summary of recent inbox messages"""

        messages_response = self.get_messages(
            label_ids=['INBOX'],
            max_results=max_results
        )

        if 'error' in messages_response or 'messages' not in messages_response:
            return []

        summaries = []

        for msg in messages_response['messages']:
            detail = self.get_message(
                msg['id'],
                format='metadata',
                metadata_headers=['From', 'Subject', 'Date']
            )

            if 'error' not in detail and 'payload' in detail:
                headers = {h['name']: h['value'] for h in detail['payload'].get('headers', [])}

                summaries.append({
                    'id': msg['id'],
                    'thread_id': msg.get('threadId'),
                    'from': headers.get('From', ''),
                    'subject': headers.get('Subject', ''),
                    'date': headers.get('Date', '')
                })

        return summaries

    def format_email_summary(self, emails: List[Dict]) -> str:
        """Format emails into natural language summary"""

        if not emails:
            return "You have no new emails."

        summary = []

        for email in emails[:3]:
            from_name = email.get('from', '').split('<')[0].strip()
            subject = email.get('subject', 'No subject')

            # Clean up from name
            from_name = from_name.replace('"', '').strip()

            summary.append(f"Email from {from_name}: {subject}")

        return ". ".join(summary) + "."

    def search_emails(self, query: str, max_results: int = 10) -> List[Dict]:
        """Search emails with query"""

        response = self.get_messages(query=query, max_results=max_results)

        if 'error' in response or 'messages' not in response:
            return []

        results = []
        for msg in response['messages'][:max_results]:
            detail = self.get_message(msg['id'])
            if 'error' not in detail:
                results.append(detail)

        return results


def get_gmail_service(instance) -> GmailService:
    """Get Gmail service for instance"""
    if not instance.google_access_token:
        return None

    return GmailService(
        access_token=instance.google_access_token,
        refresh_token=instance.google_refresh_token
    )
