#!/usr/bin/env python3
"""
Hotmart: Login via SSO (with 2FA via Gmail), create free offer 'Acesso Zory' on product 4552866
"""
import time
import re
import json
import base64
from playwright.sync_api import sync_playwright
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from googleapiclient.discovery import build

EMAIL = "mindreview.ia@gmail.com"
PASSWORD = "UNicamp@459917"
PRODUCT_ID = "4552866"
OFFER_NAME = "Acesso Zory"
SS = '/home/zory/tmp/hotmart'

CREDS_FILE = '/home/zory/.config/google/credentials.json'
TOKEN_FILE = '/home/zory/.config/google/token.json'


def get_hotmart_otp():
    """Read the latest Hotmart 2FA code from Gmail."""
    with open(TOKEN_FILE) as f:
        token_data = json.load(f)
    with open(CREDS_FILE) as f:
        creds_data = json.load(f)['installed']

    creds = Credentials(
        token=token_data.get('token'),
        refresh_token=token_data.get('refresh_token'),
        token_uri='https://oauth2.googleapis.com/token',
        client_id=creds_data['client_id'],
        client_secret=creds_data['client_secret'],
        scopes=['https://www.googleapis.com/auth/gmail.readonly']
    )
    if creds.expired:
        creds.refresh(Request())
        # Save refreshed token
        with open(TOKEN_FILE, 'w') as f:
            json.dump({
                'token': creds.token,
                'refresh_token': creds.refresh_token,
                'scopes': list(creds.scopes) if creds.scopes else [],
            }, f)

    service = build('gmail', 'v1', credentials=creds, cache_discovery=False)

    # Search for recent Hotmart verification emails
    results = service.users().messages().list(
        userId='me',
        q='from:hotmart subject:verificação OR subject:verification OR subject:código OR subject:code',
        maxResults=5
    ).execute()

    messages = results.get('messages', [])
    if not messages:
        # Broader search
        results = service.users().messages().list(
            userId='me',
            q='from:hotmart',
            maxResults=5
        ).execute()
        messages = results.get('messages', [])

    if not messages:
        print("    No Hotmart emails found!")
        return None

    # Get the most recent message
    msg = service.users().messages().get(userId='me', id=messages[0]['id'], format='full').execute()
    snippet = msg.get('snippet', '')
    print(f"    Email snippet: {snippet[:200]}")

    # Extract OTP code from snippet (usually 6 digits)
    code_match = re.search(r'\b(\d{6})\b', snippet)
    if code_match:
        return code_match.group(1)

    # Try from body
    payload = msg.get('payload', {})
    parts = payload.get('parts', [payload])
    for part in parts:
        body_data = part.get('body', {}).get('data', '')
        if body_data:
            decoded = base64.urlsafe_b64decode(body_data).decode('utf-8', errors='ignore')
            code_match = re.search(r'\b(\d{6})\b', decoded)
            if code_match:
                return code_match.group(1)
            # Also try larger codes
            code_match = re.search(r'\b(\d{4,8})\b', decoded)
            if code_match:
                return code_match.group(1)

    print(f"    Could not extract OTP from email")
    return None


def ss(page, name):
    page.screenshot(path=f'{SS}_{name}.png')


def run():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True, args=[
            '--no-sandbox', '--disable-dev-shm-usage',
            '--disable-blink-features=AutomationControlled'
        ])
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            locale='pt-BR',
            user_agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
        )
        context.add_init_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
        page = context.new_page()

        # Capture API responses
        captured = []
        def on_resp(resp):
            u = resp.url.lower()
            if any(k in u for k in ['offer', 'checkout', 'payment']):
                try: body = resp.text()
                except: body = ''
                captured.append({'url': resp.url, 'status': resp.status, 'body': body[:3000]})
        page.on('response', on_resp)

        # ─── LOGIN ───
        print("[1] Loading Hotmart SSO...")
        page.goto('https://sso.hotmart.com/login', wait_until='domcontentloaded', timeout=60000)
        page.wait_for_selector('input:visible', timeout=60000)
        time.sleep(2)
        ss(page, '01_login')

        # Fill email
        print("[2] Filling credentials...")
        page.locator('#username').fill(EMAIL)
        page.locator('#password').fill(PASSWORD)
        ss(page, '02_filled')

        # Submit
        print("[3] Submitting login...")
        page.locator('button:has-text("Entrar")').click()

        # Wait for 2FA page
        print("[4] Waiting for 2FA page...")
        time.sleep(5)
        ss(page, '03_2fa')
        print(f"    URL: {page.url}")
        body_text = page.inner_text('body')
        print(f"    Text: {body_text[:300]}")

        # Check if 2FA is required
        if 'verificação' in body_text.lower() or 'código' in body_text.lower() or 'verification' in body_text.lower():
            print("[5] 2FA detected! Fetching OTP from Gmail...")
            time.sleep(5)  # Wait for email to arrive

            otp = get_hotmart_otp()
            if not otp:
                print("    Retrying OTP in 10s...")
                time.sleep(10)
                otp = get_hotmart_otp()

            if otp:
                print(f"    OTP code: {otp}")

                # Find OTP input and fill it
                otp_filled = False
                for sel in [
                    'input[type="text"]:visible', 'input[type="number"]:visible',
                    'input[name*="code"]', 'input[name*="otp"]', 'input[name*="token"]',
                    'input[placeholder*="código"]', 'input[placeholder*="code"]',
                    'input[maxlength="6"]', 'input[maxlength="1"]',
                ]:
                    try:
                        el = page.locator(sel).first
                        if el.is_visible(timeout=3000):
                            el.fill(otp)
                            otp_filled = True
                            print(f"    OTP filled via: {sel}")
                            break
                    except:
                        continue

                if not otp_filled:
                    # Dump visible inputs
                    vis = page.locator('input:visible')
                    c = vis.count()
                    print(f"    Visible inputs: {c}")
                    for i in range(c):
                        html = vis.nth(i).evaluate('e => e.outerHTML')
                        print(f"    [{i}] {html[:150]}")
                    if c > 0:
                        vis.first.fill(otp)
                        otp_filled = True
                        print("    OTP filled in first visible input")

                ss(page, '04_otp_filled')

                # Click verify button
                for sel in [
                    'button:has-text("Verificar")', 'button:has-text("Verify")',
                    'button:has-text("Confirmar")', 'button:has-text("Enviar")',
                    'button[type="submit"]',
                ]:
                    try:
                        el = page.locator(sel).first
                        if el.is_visible(timeout=2000):
                            el.click()
                            print(f"    Clicked verify: {sel}")
                            break
                    except:
                        continue

                # Wait for redirect after 2FA
                print("[6] Waiting for post-2FA redirect...")
                try:
                    page.wait_for_url(lambda u: 'dashboard' in u or 'tools' in u or 'app-vlc' in u, timeout=30000)
                    print(f"    ✓ Redirected: {page.url}")
                except:
                    time.sleep(10)
                    print(f"    URL: {page.url}")
            else:
                print("    FAILED to get OTP!")
                browser.close()
                return
        else:
            # No 2FA, check if we're already logged in
            print("[5] No 2FA detected")
            try:
                page.wait_for_url(lambda u: 'dashboard' in u or 'tools' in u, timeout=15000)
            except:
                time.sleep(5)

        ss(page, '05_logged_in')
        print(f"    Logged in URL: {page.url}")

        # ─── NAVIGATE TO OFFERS ───
        print(f"\n[7] Going to product {PRODUCT_ID} offers...")
        page.goto(f'https://app-vlc.hotmart.com/tools/{PRODUCT_ID}/offers', wait_until='domcontentloaded', timeout=60000)
        time.sleep(8)
        ss(page, '06_offers')
        print(f"    URL: {page.url}")

        body_text = page.inner_text('body')
        print(f"    Page: {body_text[:400]}")

        # If page not found, the URL format might be different
        if 'não encontrada' in body_text or 'not found' in body_text.lower():
            print("    Page not found, trying alternative URL...")
            # Try the new Hotmart dashboard URL format
            page.goto(f'https://app-vlc.hotmart.com/products/{PRODUCT_ID}/offers', wait_until='domcontentloaded', timeout=60000)
            time.sleep(5)
            ss(page, '06b_alt_url')
            body_text = page.inner_text('body')
            print(f"    Alt URL: {page.url}")
            print(f"    Alt Page: {body_text[:300]}")

        # ─── CREATE OFFER ───
        print("\n[8] Looking for create offer...")
        create_found = False
        for sel in [
            'button:has-text("Criar oferta")', 'button:has-text("Nova oferta")',
            'a:has-text("Criar oferta")', 'a:has-text("Nova oferta")',
            'button:has-text("Create")', 'a:has-text("Create")',
            'button:has-text("Adicionar")', '[data-testid*="create"]',
        ]:
            try:
                el = page.locator(sel).first
                if el.is_visible(timeout=2000):
                    el.click()
                    create_found = True
                    print(f"    Clicked: {sel}")
                    break
            except:
                continue

        if not create_found:
            # Try direct URL
            for url in [
                f'https://app-vlc.hotmart.com/tools/{PRODUCT_ID}/offers/create',
                f'https://app-vlc.hotmart.com/products/{PRODUCT_ID}/offers/create',
            ]:
                page.goto(url, wait_until='domcontentloaded', timeout=60000)
                time.sleep(5)
                txt = page.inner_text('body')
                if 'não encontrada' not in txt:
                    print(f"    Create form at: {url}")
                    break

        time.sleep(3)
        ss(page, '07_create')
        print(f"    URL: {page.url}")

        body_text = page.inner_text('body')
        print(f"    Form: {body_text[:500]}")

        # Dump visible form elements
        vis = page.locator('input:visible, select:visible, textarea:visible')
        c = vis.count()
        print(f"    Visible elements: {c}")
        for i in range(min(c, 15)):
            html = vis.nth(i).evaluate('e => e.outerHTML')
            print(f"    [{i}] {html[:150]}")

        # Fill name
        print("\n[9] Filling offer form...")
        for sel in ['input[name="name"]', 'input[name="offerName"]', 'input[placeholder*="nome" i]', 'input[type="text"]:visible']:
            try:
                el = page.locator(sel).first
                if el.is_visible(timeout=2000):
                    el.fill(OFFER_NAME)
                    print(f"    Name: {sel}")
                    break
            except:
                continue

        # Free / price=0
        for sel in ['label:has-text("Gratuito")', 'span:has-text("Gratuito")', 'label:has-text("Free")']:
            try:
                el = page.locator(sel).first
                if el.is_visible(timeout=2000):
                    el.click()
                    print(f"    Free: {sel}")
                    break
            except:
                continue

        for sel in ['input[name="price"]', 'input[name*="price"]', 'input[name*="valor"]', 'input[type="number"]:visible']:
            try:
                el = page.locator(sel).first
                if el.is_visible(timeout=2000):
                    el.fill('0')
                    print(f"    Price=0: {sel}")
                    break
            except:
                continue

        ss(page, '08_filled')

        # Submit
        print("\n[10] Saving...")
        for sel in ['button:has-text("Salvar")', 'button:has-text("Criar")', 'button:has-text("Save")', 'button[type="submit"]']:
            try:
                el = page.locator(sel).first
                if el.is_visible(timeout=2000):
                    el.click()
                    print(f"    Submit: {sel}")
                    break
            except:
                continue

        time.sleep(5)
        ss(page, '09_saved')

        # ─── EXTRACT CHECKOUT CODE ───
        print("\n[11] Looking for checkout code...")
        html = page.content()
        body = page.inner_text('body')
        print(f"    Body: {body[:300]}")

        patterns = [
            r'pay\.hotmart\.com/([A-Za-z0-9]+)',
            r'checkout[/_-]?(?:code|link)?[:\s="\']+([A-Z0-9]{6,})',
            r'[Cc]ódigo[:\s]+([A-Z0-9]+)',
        ]
        for pat in patterns:
            for src in [body, html]:
                m = re.search(pat, src, re.IGNORECASE)
                if m:
                    print(f"    ✓ CHECKOUT CODE: {m.group(1)}")

        for el in page.locator('a[href*="pay.hotmart"]').all():
            print(f"    Pay link: {el.get_attribute('href')}")

        if captured:
            print("\n[API]:")
            for r in captured[:10]:
                print(f"    {r['status']} {r['url'][:120]}")

        # Check offers list
        print("\n[12] Offers list...")
        page.goto(f'https://app-vlc.hotmart.com/tools/{PRODUCT_ID}/offers', wait_until='domcontentloaded', timeout=60000)
        time.sleep(5)
        ss(page, '10_list')
        print(f"    {page.inner_text('body')[:400]}")

        print(f"\n[DONE] {page.url}")
        ss(page, 'final')
        browser.close()

if __name__ == '__main__':
    run()
