import asyncio
import time
import requests
import datetime
import os
import sys
import json
import logging
from pyppeteer import launch
from tqdm import tqdm

# --- CARGA DE CONFIGURACIÓN ---
def load_config():
    try:
        with open('config.json', 'r') as f:
            return json.load(f)
    except Exception as e:
        print(f"Error crítico: No se pudo leer config.json: {e}")
        sys.exit(1)

CONFIG = load_config()

# --- CONFIGURACIÓN DE INSTANCIA
if len(sys.argv) < 3:
    # Si falla por falta de parámetros, activamos modo debug
    CLIENTE_ID = "0"
    ID_TAKEN = "7"
    print(f"MODO DEBUG: Usando parámetros por defecto ({CLIENTE_ID}_{ID_TAKEN})")
else:
    CLIENTE_ID = sys.argv[1]
    ID_TAKEN = sys.argv[2]

INSTANCE_ID = f"{CLIENTE_ID}_{ID_TAKEN}"
LOCK_FILE = f"lock_{INSTANCE_ID}.lock"
LOG_FILE = f"log_{INSTANCE_ID}.txt"
URLS = CONFIG['API_URLS']

# --- CONFIGURACIÓN DE LOGS ---
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[logging.FileHandler(LOG_FILE, encoding='utf-8')]
)
logger = logging.getLogger(__name__)

def create_lock():
    if os.path.exists(LOCK_FILE):
        print(f"Instancia {INSTANCE_ID} ya está corriendo. Abortar.")
        sys.exit(0)
    with open(LOCK_FILE, 'w') as f:
        f.write(str(os.getpid()))

def remove_lock():
    if os.path.exists(LOCK_FILE):
        os.remove(LOCK_FILE)

def extrer_cuils_db(cliente, id_taken):
    try:
        endpoint = f"{URLS['LISTADO']}?cliente={cliente}&id_taken={id_taken}"
        response = requests.get(endpoint, timeout=30)
        return response.json() if response.status_code == 200 else []
    except Exception as e:
        logger.error(f"Error API Listado: {e}")
        return []

async def afip_aportes(cuil):
    browser = await launch({
        'headless': True,
        'executablePath': CONFIG['CHROME_PATH'],
        'args': ['--no-sandbox', '--disable-setuid-sandbox']
    })
    try:
        page = await browser.newPage()
        await page.goto("https://serviciosweb.afip.gob.ar/TRAMITES_CON_CLAVE_FISCAL/MISAPORTES/app/basica.aspx", 
                        timeout=CONFIG['BROWSER_TIMEOUT_MS'])
        
        await page.waitForSelector('input[id="ctl00_ContentPlaceHolder2_txtCuil_txtSufijo"]')
        await page.click('.TextSufijo')
        for _ in range(12): await page.keyboard.press('ArrowLeft')
        await page.type('input[id="ctl00_ContentPlaceHolder2_txtCuil_txtSufijo"]', str(cuil['CUIL']))
        
        await page.click('.Boton')
        await page.waitForNavigation()

        # Validación AFIP (CUIT/Captcha/Etc)
        if await page.querySelector('.TextoIngresoDatos'):
            requests.get(f"{URLS['PROCESADO']}?proceso={cuil['proceso']}&id={cuil['id']}")
            return False, "REQ_AFIP"

        # Validación Sin Aportes
        if await page.querySelector(".TablaBasicaError"):
            requests.get(f"{URLS['PROCESADO']}?proceso={cuil['proceso']}&id={cuil['id']}")
            return False, "SIN_APORTES"

        # Éxito
        requests.get(f"{URLS['PROCESADO']}?proceso={cuil['proceso']}&id={cuil['id']}")
        html = await page.content()
        input_hLst = await page.querySelector('input[id="ctl00_ContentPlaceHolder2_hLst"]')
        cuit_full = await page.evaluate('(el) => el.value', input_hLst)
        
        requests.post(URLS['HTML'], data={'cuit': cuit_full[0:11], 'cuil': cuil['CUIL'], 'info': html})
        return True, "OK"

    except Exception as e:
        logger.error(f"Error en CUIL {cuil['CUIL']}: {e}")
        return False, "ERROR"
    finally:
        await browser.close()

async def main_loop(cliente, id_taken):
    while True:
        try:
            cuils = extrer_cuils_db(cliente, id_taken)
            
            if not cuils:
                print(f"[{datetime.datetime.now().strftime('%H:%M:%S')}] 💤 Sin datos. Esperando {CONFIG['WAIT_NO_DATA_MINUTES']}m...", end='\r')
                await asyncio.sleep(CONFIG['WAIT_NO_DATA_MINUTES'] * 60)
                continue

            # BARRA DE PROGRESO
            print(f"\nLote recibido: {len(cuils)} registros para {INSTANCE_ID}")
            pbar = tqdm(total=len(cuils), desc=f"Instancia {INSTANCE_ID}", unit="cuil")
            
            for c in cuils:
                # Actualizamos el sufijo de la barra con el CUIL actual
                pbar.set_postfix_str(f"Procesando: {c['CUIL']}")
                
                success, status = await afip_aportes(c)
                
                logger.info(f"CUIL: {c['CUIL']} | Status: {status}")
                pbar.update(1)
                await asyncio.sleep(0.5)
            
            pbar.close()
            print(f"Lote finalizado. Buscando más datos...")

        except Exception as e:
            logger.critical(f"Error crítico: {e}")
            print(f"\n Error. Reintentando en {CONFIG['WAIT_ERROR_MINUTES']}m...")
            await asyncio.sleep(CONFIG['WAIT_ERROR_MINUTES'] * 60)

if __name__ == "__main__":
    create_lock()
    try:
        asyncio.run(main_loop(CLIENTE_ID, ID_TAKEN))
    finally:
        remove_lock()
