#!/usr/bin/env python3
"""
Newsletter Email Server - Gmail API OAuth2
==========================================
Backend para envio de newsletters via Gmail API
Porta: 5060

Uso:
    python3 newsletter-email-server.py

Endpoints:
    POST /api/send-email    - Envia email HTML
    GET  /api/health        - Health check
    GET  /api/auth          - Inicia autenticação OAuth2
    GET  /api/auth/callback - Callback OAuth2

Configuração:
    1. Criar projeto no Google Cloud Console
    2. Ativar Gmail API
    3. Criar credenciais OAuth2 (Desktop App)
    4. Baixar credentials.json para este diretório
    5. Rodar o servidor e acessar /api/auth para autenticar

Autor: Neog
Email: gomes@xneog.com
"""

import os
import json
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
from pathlib import Path

from flask import Flask, request, jsonify, redirect
from flask_cors import CORS

# Gmail API imports
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

app = Flask(__name__)
CORS(app)  # Permite chamadas do iOS

# Configurações
PORT = 5060
SCOPES = ['https://www.googleapis.com/auth/gmail.send']
CREDENTIALS_FILE = 'credentials.json'
TOKEN_FILE = 'token.json'
SENDER_EMAIL = 'gomes@xneog.com'

# Diretório base
BASE_DIR = Path(__file__).parent

def get_credentials_path():
    """Retorna caminho do credentials.json"""
    return BASE_DIR / CREDENTIALS_FILE

def get_token_path():
    """Retorna caminho do token.json"""
    return BASE_DIR / TOKEN_FILE

def get_gmail_service():
    """Obtém serviço Gmail API autenticado"""
    creds = None
    token_path = get_token_path()

    # Carrega token existente
    if token_path.exists():
        creds = Credentials.from_authorized_user_file(str(token_path), SCOPES)

    # Se não tem credenciais válidas
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            # Renova token
            creds.refresh(Request())
            # Salva token renovado
            with open(token_path, 'w') as f:
                f.write(creds.to_json())
        else:
            return None

    return build('gmail', 'v1', credentials=creds)

def create_html_email(to: str, subject: str, html_body: str) -> dict:
    """Cria email HTML no formato da Gmail API"""
    message = MIMEMultipart('alternative')
    message['to'] = to
    message['from'] = f"Neog Newsletter <{SENDER_EMAIL}>"
    message['subject'] = subject

    # Adiciona versão texto
    text_part = MIMEText(html_to_text(html_body), 'plain')
    message.attach(text_part)

    # Adiciona versão HTML
    html_part = MIMEText(html_body, 'html')
    message.attach(html_part)

    # Codifica em base64
    raw = base64.urlsafe_b64encode(message.as_bytes()).decode()
    return {'raw': raw}

def html_to_text(html: str) -> str:
    """Converte HTML para texto simples (básico)"""
    import re
    # Remove tags HTML
    text = re.sub(r'<br\s*/?>', '\n', html)
    text = re.sub(r'<p[^>]*>', '\n', text)
    text = re.sub(r'</p>', '\n', text)
    text = re.sub(r'<[^>]+>', '', text)
    # Decodifica entidades
    text = text.replace('&nbsp;', ' ')
    text = text.replace('&amp;', '&')
    text = text.replace('&lt;', '<')
    text = text.replace('&gt;', '>')
    return text.strip()

# ============================================
# ENDPOINTS
# ============================================

@app.route('/api/health', methods=['GET'])
def health():
    """Health check"""
    service = get_gmail_service()
    return jsonify({
        'status': 'ok',
        'authenticated': service is not None,
        'sender': SENDER_EMAIL,
        'timestamp': datetime.now().isoformat()
    })

@app.route('/api/auth', methods=['GET'])
def auth():
    """Inicia autenticação OAuth2"""
    creds_path = get_credentials_path()

    if not creds_path.exists():
        return jsonify({
            'error': 'credentials.json não encontrado',
            'instructions': [
                '1. Acesse console.cloud.google.com',
                '2. Crie um projeto ou selecione existente',
                '3. Ative a Gmail API',
                '4. Vá em Credentials > Create Credentials > OAuth client ID',
                '5. Selecione "Desktop app"',
                '6. Baixe o JSON e salve como credentials.json neste diretório'
            ]
        }), 400

    try:
        flow = Flow.from_client_secrets_file(
            str(creds_path),
            scopes=SCOPES,
            redirect_uri=f'http://localhost:{PORT}/api/auth/callback'
        )

        auth_url, state = flow.authorization_url(
            access_type='offline',
            include_granted_scopes='true'
        )

        return jsonify({
            'message': 'Abra a URL abaixo no navegador para autenticar',
            'auth_url': auth_url,
            'state': state
        })

    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/auth/callback', methods=['GET', 'POST'])
def auth_callback():
    """Callback OAuth2 - recebe código de autorização"""
    # Suporta GET (redirect do Google) ou POST (manual)
    if request.method == 'POST':
        data = request.get_json() or {}
        code = data.get('code')
    else:
        code = request.args.get('code')

    if not code:
        return jsonify({'error': 'Código de autorização não encontrado'}), 400

    try:
        creds_path = get_credentials_path()
        flow = Flow.from_client_secrets_file(
            str(creds_path),
            scopes=SCOPES,
            redirect_uri=f'http://localhost:{PORT}/api/auth/callback'
        )

        # Troca código por token
        flow.fetch_token(code=code)
        creds = flow.credentials

        # Salva token
        token_path = get_token_path()
        with open(token_path, 'w') as f:
            f.write(creds.to_json())

        return jsonify({
            'success': True,
            'message': f'Autenticação concluída! Token salvo em {token_path}',
            'sender': SENDER_EMAIL
        })

    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/send-email', methods=['POST'])
def send_email():
    """
    Envia email via Gmail API

    Body JSON:
    {
        "to": ["email1@example.com", "email2@example.com"],
        "subject": "Assunto do email",
        "html": "<html>...</html>"
    }
    """
    service = get_gmail_service()

    if not service:
        return jsonify({
            'error': 'Não autenticado',
            'action': 'Acesse /api/auth para autenticar'
        }), 401

    try:
        data = request.get_json()

        # Valida campos obrigatórios
        if not data:
            return jsonify({'error': 'Body JSON obrigatório'}), 400

        recipients = data.get('to', [])
        subject = data.get('subject', 'Newsletter')
        html_body = data.get('html', '')

        if not recipients:
            return jsonify({'error': 'Campo "to" obrigatório (lista de emails)'}), 400

        if not html_body:
            return jsonify({'error': 'Campo "html" obrigatório'}), 400

        # Converte para lista se string
        if isinstance(recipients, str):
            recipients = [recipients]

        # Envia para cada destinatário
        results = []
        for recipient in recipients:
            try:
                message = create_html_email(recipient, subject, html_body)
                sent = service.users().messages().send(
                    userId='me',
                    body=message
                ).execute()

                results.append({
                    'email': recipient,
                    'status': 'sent',
                    'messageId': sent.get('id')
                })
                print(f"✅ Email enviado para {recipient}")

            except HttpError as e:
                results.append({
                    'email': recipient,
                    'status': 'failed',
                    'error': str(e)
                })
                print(f"❌ Falha ao enviar para {recipient}: {e}")

        # Conta sucessos
        sent_count = sum(1 for r in results if r['status'] == 'sent')

        return jsonify({
            'success': sent_count > 0,
            'sent': sent_count,
            'total': len(recipients),
            'results': results,
            'timestamp': datetime.now().isoformat()
        })

    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/test-send', methods=['GET'])
def test_send():
    """Endpoint de teste - envia email de teste"""
    service = get_gmail_service()

    if not service:
        return jsonify({
            'error': 'Não autenticado',
            'action': 'Acesse /api/auth para autenticar'
        }), 401

    test_email = 'leandro.1416.ls.ls@gmail.com'
    test_html = """
    <html>
    <body style="font-family: Arial, sans-serif; padding: 20px;">
        <h1 style="color: #007AFF;">Newsletter Test</h1>
        <p>Este é um email de teste do NewsletterMaker.</p>
        <p>Se você está vendo isso, a integração Gmail API está funcionando!</p>
        <br>
        <p>— Neog</p>
        <hr>
        <small style="color: #666;">Enviado via NewsletterMaker • gomes@xneog.com</small>
    </body>
    </html>
    """

    try:
        message = create_html_email(test_email, 'NewsletterMaker - Teste Gmail API', test_html)
        sent = service.users().messages().send(userId='me', body=message).execute()

        return jsonify({
            'success': True,
            'message': f'Email de teste enviado para {test_email}',
            'messageId': sent.get('id')
        })

    except HttpError as e:
        return jsonify({'error': str(e)}), 500

# ============================================
# MAIN
# ============================================

if __name__ == '__main__':
    print("=" * 50)
    print("Newsletter Email Server - Gmail API OAuth2")
    print("=" * 50)
    print(f"Porta: {PORT}")
    print(f"Sender: {SENDER_EMAIL}")
    print()

    # Verifica credentials.json
    creds_path = get_credentials_path()
    if creds_path.exists():
        print(f"✅ credentials.json encontrado")
    else:
        print(f"⚠️  credentials.json NÃO encontrado")
        print("   Baixe de console.cloud.google.com")

    # Verifica token.json
    token_path = get_token_path()
    if token_path.exists():
        print(f"✅ token.json encontrado (autenticado)")
    else:
        print(f"⚠️  token.json NÃO encontrado")
        print(f"   Acesse http://localhost:{PORT}/api/auth para autenticar")

    print()
    print("Endpoints:")
    print(f"  GET  http://localhost:{PORT}/api/health")
    print(f"  GET  http://localhost:{PORT}/api/auth")
    print(f"  POST http://localhost:{PORT}/api/send-email")
    print(f"  GET  http://localhost:{PORT}/api/test-send")
    print()
    print("=" * 50)

    app.run(host='0.0.0.0', port=PORT, debug=True)
