#!/usr/bin/env python3
"""
Twitter/X Auto-Poster via Safari (macOS)
Automatiza posts no Twitter usando Safari e AppleScript

Requisitos:
- macOS
- Safari com login no Twitter/X
- Permissões de Acessibilidade habilitadas para Terminal/Python

Uso:
    python3 twitter-post.py "Seu tweet aqui"
    python3 twitter-post.py --interactive
"""

import subprocess
import time
import sys
import argparse


def run_applescript(script: str) -> str:
    """Executa AppleScript e retorna o resultado."""
    result = subprocess.run(
        ["osascript", "-e", script],
        capture_output=True,
        text=True
    )
    if result.returncode != 0:
        raise Exception(f"AppleScript error: {result.stderr}")
    return result.stdout.strip()


def open_twitter_compose():
    """Abre o Safari no Twitter/X na página de composição."""
    script = '''
    tell application "Safari"
        activate

        -- Verifica se já existe uma janela
        if (count of windows) = 0 then
            make new document
        end if

        -- Abre o Twitter compose
        set URL of front document to "https://twitter.com/compose/tweet"
    end tell
    '''
    run_applescript(script)
    print("✓ Safari aberto no Twitter compose")


def wait_for_page_load(timeout: int = 10):
    """Aguarda a página carregar."""
    print("⏳ Aguardando página carregar...", end="", flush=True)

    for i in range(timeout):
        time.sleep(1)
        print(".", end="", flush=True)

        # Verifica se a página carregou
        script = '''
        tell application "Safari"
            set pageState to do JavaScript "document.readyState" in front document
            return pageState
        end tell
        '''
        try:
            state = run_applescript(script)
            if state == "complete":
                print(" ✓")
                return True
        except:
            pass

    print(" (timeout)")
    return False


def type_tweet(text: str):
    """Digita o texto do tweet usando System Events."""
    # Escapa caracteres especiais para AppleScript
    escaped_text = text.replace("\\", "\\\\").replace('"', '\\"')

    script = f'''
    tell application "Safari" to activate
    delay 0.5

    tell application "System Events"
        tell process "Safari"
            -- Clica na área de texto do tweet
            keystroke tab
            delay 0.3

            -- Digita o texto
            keystroke "{escaped_text}"
        end tell
    end tell
    '''
    run_applescript(script)
    suffix = "..." if len(text) > 50 else ""
    print(f"✓ Tweet digitado: {text[:50]}{suffix}")


def type_tweet_js(text: str):
    """Digita o tweet via JavaScript direto no DOM (sem precisar de keystroke)."""
    # Escapa o texto para JavaScript
    escaped = text.replace("\\", "\\\\").replace("'", "\\'").replace('"', '\\"').replace("\n", "\\n").replace("\r", "")

    # Monta o JavaScript como string separada
    js = f"(function(){{var e=document.querySelector('[data-testid=\"tweetTextarea_0\"]')||document.querySelector('[role=\"textbox\"]');if(!e)return'nf';e.focus();var c=e.querySelector('[contenteditable=\"true\"]')||e;c.focus();document.execCommand('insertText',false,'{escaped}');return'ok'}})()"

    # Salva JS em arquivo temporário com encoding UTF-8
    import tempfile
    with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False, encoding='utf-8') as f:
        f.write(js)
        js_file = f.name

    script = f'''
    tell application "Safari"
        activate
        delay 0.5
        set jsCode to read POSIX file "{js_file}" as «class utf8»
        do JavaScript jsCode in front document
    end tell
    '''

    try:
        result = run_applescript(script)
        import os
        os.unlink(js_file)

        if "ok" in str(result) or result == "ok":
            time.sleep(0.3)
            suffix = "..." if len(text) > 50 else ""
            print(f"✓ Tweet digitado: {text[:50]}{suffix}")
        elif "nf" in str(result):
            print("⚠ Editor não encontrado")
            raise Exception("Editor não encontrado")
        else:
            # Mesmo sem retorno claro, pode ter funcionado
            time.sleep(0.3)
            suffix = "..." if len(text) > 50 else ""
            print(f"✓ Tweet digitado: {text[:50]}{suffix}")
    except Exception as e:
        print(f"⚠ Erro: {e}")
        raise


def type_tweet_clipboard(text: str):
    """Fallback: usa clipboard + paste via AppleScript."""
    # Copia texto para clipboard
    process = subprocess.Popen(['pbcopy'], stdin=subprocess.PIPE)
    process.communicate(text.encode('utf-8'))

    # Tenta colar - isso pode falhar sem permissões de Acessibilidade
    paste_script = '''
    tell application "Safari"
        activate
    end tell
    tell application "System Events"
        tell process "Safari"
            keystroke "v" using command down
        end tell
    end tell
    '''
    try:
        run_applescript(paste_script)
        time.sleep(0.3)
        suffix = "..." if len(text) > 50 else ""
        print(f"✓ Tweet colado: {text[:50]}{suffix}")
    except Exception as e:
        print(f"❌ Falha ao colar: {e}")
        raise


def click_post_button():
    """Clica no botão de postar."""
    script = '''
    tell application "Safari"
        activate
        delay 0.3

        -- Clica no botão Post via JavaScript
        set js to "
            (function() {
                // Botão 'Post' ou 'Postar'
                var btn = document.querySelector('[data-testid=\\"tweetButton\\"]');
                if (!btn) {
                    btn = document.querySelector('[data-testid=\\"tweetButtonInline\\"]');
                }
                if (btn && !btn.disabled) {
                    btn.click();
                    return 'clicked';
                }
                return 'not_found';
            })()
        "

        set result to do JavaScript js in front document
        return result
    end tell
    '''

    result = run_applescript(script)

    if result == "clicked":
        print("✓ Botão Post clicado!")
        return True
    else:
        print("⚠ Botão Post não encontrado ou desabilitado")
        # Tenta via keyboard shortcut (Cmd+Enter)
        shortcut_script = '''
        tell application "System Events"
            tell process "Safari"
                keystroke return using command down
            end tell
        end tell
        '''
        run_applescript(shortcut_script)
        print("✓ Tentou postar via Cmd+Enter")
        return True


def get_last_tweet_url(username: str = "Gomesnzt") -> str:
    """Obtém a URL do último tweet postado (ignora tweets fixados/pinned e duplicatas)."""
    time.sleep(2)  # Aguarda o tweet ser postado

    script = f'''
    tell application "Safari"
        -- Navega para o perfil do usuário
        set URL of front document to "https://x.com/{username}"
    end tell
    '''
    run_applescript(script)

    # Aguarda página carregar completamente
    print("⏳ Carregando perfil...", end="", flush=True)
    for _ in range(8):
        time.sleep(1)
        print(".", end="", flush=True)
    print(" ✓")

    # Obtém a URL do tweet mais recente (ignora pinned)
    js_code = '''(function(){var tweets=document.querySelectorAll('article[data-testid="tweet"]');for(var i=0;i<tweets.length;i++){var t=tweets[i];if((t.innerText||'').indexOf('Pinned')<0&&(t.innerText||'').indexOf('Fixado')<0){var link=t.querySelector('a[href*="/status/"]');if(link)return link.href;}}return '';})()'''

    # Escapa para AppleScript
    js_escaped = js_code.replace('\\', '\\\\').replace('"', '\\"')

    script = f'''
    tell application "Safari"
        set result to do JavaScript "{js_escaped}" in front document
        return result
    end tell
    '''

    try:
        url = run_applescript(script)
        if url and "/status/" in url:
            print(f"✓ URL do tweet: {url}")
            return url
        else:
            print(f"⚠ URL não encontrada")
    except Exception as e:
        print(f"⚠ Erro ao obter URL: {e}")

    return ""


def reply_to_url(tweet_url: str, text: str) -> bool:
    """Responde a um tweet específico via URL."""
    if len(text) > 280:
        print(f"⚠ Reply muito longo ({len(text)}/280 caracteres)")
        text = text[:280]

    print(f"\n🧵 Respondendo ao tweet ({len(text)}/280 caracteres)")
    print("-" * 50)

    # 1. Abre o tweet original
    script = f'''
    tell application "Safari"
        activate
        set URL of front document to "{tweet_url}"
    end tell
    '''
    run_applescript(script)

    # 2. Aguarda carregar
    if not wait_for_page_load(10):
        print("❌ Página não carregou")
        return False

    time.sleep(2)

    # 3. Clica no botão de reply
    script = '''
    tell application "Safari"
        set js to "
            (function() {
                var replyBtn = document.querySelector('[data-testid=\\"reply\\"]');
                if (replyBtn) {
                    replyBtn.click();
                    return 'clicked';
                }
                return 'not_found';
            })()
        "
        set result to do JavaScript js in front document
        return result
    end tell
    '''

    result = run_applescript(script)
    if result != "clicked":
        print("⚠ Botão reply não encontrado")
        return False

    print("✓ Caixa de reply aberta")

    # 4. Aguarda modal abrir
    time.sleep(1.5)

    # 5. Digita o reply
    type_tweet_js(text)

    # 6. Posta
    time.sleep(1)
    click_post_button()

    print("✅ Reply postado!")
    return True


def post_thread(tweets: list, username: str = "Gomesnzt") -> bool:
    """
    Posta uma thread completa no Twitter.

    Args:
        tweets: Lista de strings, cada uma é um tweet da thread
        username: Nome de usuário para encontrar o tweet postado

    Returns:
        True se toda a thread foi postada com sucesso
    """
    if not tweets:
        print("❌ Nenhum tweet para postar")
        return False

    print(f"\n🧵 Postando thread com {len(tweets)} tweets")
    print("=" * 50)

    # 1. Posta o primeiro tweet
    print(f"\n📝 Tweet 1/{len(tweets)}")
    if not post_tweet(tweets[0], auto_post=True):
        print("❌ Falha ao postar primeiro tweet")
        return False

    # Se só tem um tweet, terminou
    if len(tweets) == 1:
        return True

    # 2. Obtém URL do primeiro tweet
    tweet_url = get_last_tweet_url(username)
    if not tweet_url:
        print("⚠ Não conseguiu obter URL do tweet. Tentando método alternativo...")
        # Fallback: usa reply_to_tweet que vai para home
        for i, tweet_text in enumerate(tweets[1:], start=2):
            print(f"\n📝 Tweet {i}/{len(tweets)}")
            time.sleep(2)
            reply_to_tweet(tweet_text)
        return True

    # 3. Posta os replies usando a URL
    current_url = tweet_url
    for i, tweet_text in enumerate(tweets[1:], start=2):
        print(f"\n📝 Tweet {i}/{len(tweets)}")
        time.sleep(2)

        if reply_to_url(current_url, tweet_text):
            # Atualiza URL para o novo tweet (para encadear replies)
            new_url = get_last_tweet_url(username)
            if new_url and new_url != current_url:
                current_url = new_url
        else:
            print(f"⚠ Falha no tweet {i}, continuando...")

    print(f"\n✅ Thread completa! ({len(tweets)} tweets)")
    return True


def click_reply_to_last_tweet():
    """Clica no botão de resposta do último tweet postado."""
    script = '''
    tell application "Safari"
        activate
        delay 1

        -- Encontra e clica no botão de reply do tweet mais recente
        set js to "
            (function() {
                // Espera um pouco para o tweet ser postado
                // Encontra o primeiro tweet na timeline (o que acabamos de postar)
                var tweets = document.querySelectorAll('[data-testid=\\"tweet\\"]');
                if (tweets.length > 0) {
                    var lastTweet = tweets[0];
                    var replyBtn = lastTweet.querySelector('[data-testid=\\"reply\\"]');
                    if (replyBtn) {
                        replyBtn.click();
                        return 'clicked';
                    }
                }
                return 'not_found';
            })()
        "

        set result to do JavaScript js in front document
        return result
    end tell
    '''

    result = run_applescript(script)
    return result == "clicked"


def reply_to_tweet(text: str):
    """
    Responde ao último tweet postado (para threads).
    """
    if len(text) > 280:
        print(f"⚠ Reply muito longo ({len(text)}/280 caracteres)")
        text = text[:280]

    print(f"\n🧵 Adicionando à thread ({len(text)}/280 caracteres)")
    print("-" * 50)

    # 1. Vai para a home do Twitter (onde o tweet aparece)
    script = '''
    tell application "Safari"
        activate
        set URL of front document to "https://twitter.com/home"
    end tell
    '''
    run_applescript(script)

    # 2. Aguarda carregar
    if not wait_for_page_load(10):
        print("❌ Página não carregou")
        return False

    time.sleep(2)

    # 3. Clica no reply do último tweet
    if not click_reply_to_last_tweet():
        print("⚠ Não encontrou botão de reply. Tentando compose normal...")
        open_twitter_compose()
        time.sleep(2)

    # 4. Aguarda modal de reply abrir
    time.sleep(1.5)

    # 5. Digita o reply
    type_tweet_js(text)

    # 6. Posta
    time.sleep(1)
    click_post_button()

    print("✅ Reply adicionado à thread!")
    return True


def check_accessibility_permissions():
    """Verifica se as permissões de acessibilidade estão habilitadas."""
    script = '''
    tell application "System Events"
        set frontApp to name of first application process whose frontmost is true
        return frontApp
    end tell
    '''
    try:
        run_applescript(script)
        return True
    except:
        return False


def post_tweet(text: str, auto_post: bool = True):
    """
    Fluxo completo para postar um tweet.

    Args:
        text: O texto do tweet (máx 280 caracteres)
        auto_post: Se True, clica automaticamente no botão Post
    """
    # Validação
    if len(text) > 280:
        print(f"⚠ Tweet muito longo ({len(text)}/280 caracteres)")
        text = text[:280]
        print(f"  Truncado para: {text}")

    # Verifica permissões
    if not check_accessibility_permissions():
        print("❌ Permissões de Acessibilidade necessárias!")
        print("   Vá em: Preferências do Sistema > Privacidade > Acessibilidade")
        print("   Adicione Terminal ou a aplicação Python")
        return False

    print(f"\n🐦 Postando tweet ({len(text)}/280 caracteres)")
    print("-" * 50)

    # 1. Abre Twitter compose
    open_twitter_compose()

    # 2. Aguarda carregar
    if not wait_for_page_load(15):
        print("❌ Página não carregou a tempo")
        return False

    # 3. Aguarda mais um pouco para o editor carregar
    time.sleep(2)

    # 4. Digita o tweet
    type_tweet_js(text)

    # 5. Posta (se auto_post ativado)
    if auto_post:
        time.sleep(1)
        click_post_button()
        print("\n✅ Tweet enviado!")
    else:
        print("\n⏸ Tweet preparado. Revise e clique em Post manualmente.")
        print("  (Use --post para postar automaticamente)")

    return True


def interactive_mode():
    """Modo interativo para compor tweets."""
    print("\n🐦 Twitter Auto-Poster - Modo Interativo")
    print("=" * 50)
    print("Digite seu tweet (Enter para enviar, 'q' para sair):\n")

    while True:
        try:
            text = input("Tweet> ").strip()

            if text.lower() == 'q':
                print("Saindo...")
                break

            if not text:
                continue

            confirm = input(f"Postar automaticamente? (s/n): ").strip().lower()
            auto_post = confirm in ['s', 'sim', 'y', 'yes']

            post_tweet(text, auto_post=auto_post)
            print()

        except KeyboardInterrupt:
            print("\nSaindo...")
            break


def main():
    parser = argparse.ArgumentParser(
        description="Automatiza posts no Twitter/X via Safari",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Exemplos:
  python3 twitter-post.py "Olá mundo!"        # Posta automaticamente
  python3 twitter-post.py "Meu tweet" -n      # Apenas prepara (não posta)
  python3 twitter-post.py --interactive

Notas:
  - Requer login no Twitter via Safari
  - Habilite Acessibilidade em Preferências do Sistema
  - Por padrão, posta automaticamente. Use -n para revisar antes.
        """
    )

    parser.add_argument(
        "tweet",
        nargs="?",
        help="Texto do tweet (máx 280 caracteres)"
    )

    parser.add_argument(
        "--no-post", "-n",
        action="store_true",
        help="NÃO posta automaticamente (apenas prepara o tweet)"
    )

    parser.add_argument(
        "--interactive", "-i",
        action="store_true",
        help="Modo interativo para múltiplos tweets"
    )

    parser.add_argument(
        "--reply", "-r",
        action="store_true",
        help="Posta como reply ao último tweet (para threads)"
    )

    parser.add_argument(
        "--thread", "-t",
        type=str,
        help="JSON array de tweets para postar como thread"
    )

    parser.add_argument(
        "--username", "-u",
        type=str,
        default="Gomesnzt",
        help="Username do Twitter para buscar URL do tweet (default: Gomesnzt)"
    )

    args = parser.parse_args()

    if args.interactive:
        interactive_mode()
    elif args.thread:
        # Modo thread: recebe JSON array de tweets
        import json
        try:
            tweets = json.loads(args.thread)
            if isinstance(tweets, list) and len(tweets) > 0:
                post_thread(tweets, username=args.username)
            else:
                print("❌ Thread deve ser um JSON array com pelo menos 1 tweet")
                sys.exit(1)
        except json.JSONDecodeError as e:
            print(f"❌ Erro ao parsear JSON: {e}")
            sys.exit(1)
    elif args.tweet:
        if args.reply:
            # Modo reply para threads
            reply_to_tweet(args.tweet)
        else:
            post_tweet(args.tweet, auto_post=not args.no_post)
    else:
        parser.print_help()
        print("\n💡 Dica: Use --interactive para modo interativo")


if __name__ == "__main__":
    main()
