"""
Demo VeriFactu — flujo desde el front
======================================
Simula lo que haría el front al pulsar "Registrar":
  1. Login en el backend (dolibarr-bff) para obtener JWT
  2. Consulta el token VeriFactu almacenado en el backend
  3. Envía una factura en formato Dolibarr directamente a VerifactuMidAPI

Uso:
  python demo.py
  python demo.py --backend http://localhost:5269 --api http://localhost:6789
  python demo.py --usuario admin --password 12345678
"""

import sys
import json
import argparse
import urllib.request
import urllib.error

# ── Configuración por defecto ──────────────────────────────────────────────────
BACKEND_URL = "http://localhost:5269"
API_URL     = "http://localhost:6789"
USUARIO     = "admin"
PASSWORD    = "12345678"

# ── Factura de ejemplo ─────────────────────────────────────────────────────────
# Mismo formato que el front recibe del backend (formato Dolibarr).
# Los campos emisor.nif y emisor.nombre los rellena la API desde el certificado.
FACTURA = {
    "format": "dolibarr",
    "invoice": {
        "number": "FAC-DEMO-001",
        "date": "2026-05-29",
        "notePublic": "Servicios de consultoría tecnológica",
        "lines": [
            {
                "description": "Desarrollo integración VeriFactu",
                "quantity": 1,
                "unitPrice": 121.00,
                "taxRate": 21
            },
            {
                "description": "Soporte técnico mensual",
                "quantity": 2,
                "unitPrice": 60.50,
                "taxRate": 21
            }
        ]
    },
    "client": {
        "name": "Empresa Cliente S.L.",
        "vatNumber": "B12345678"
    },
    "emisor": {
        "nif": "",
        "nombre": ""
    },
    "sistema": {
        "nombre": "BYolivia Suite",
        "nif_proveedor": "B87654321",
        "version": "1.0.0"
    }
}

# ── Helpers ────────────────────────────────────────────────────────────────────

def _color(text, code):
    return f"\033[{code}m{text}\033[0m"

def ok(msg):     print(_color(f"  ✓  {msg}", "32"))
def err(msg):    print(_color(f"  ✗  {msg}", "31"))
def info(msg):   print(_color(f"  →  {msg}", "36"))
def titulo(msg): print(_color(f"\n{'─'*60}\n  {msg}\n{'─'*60}", "34"))

def hacer_request(method, url, headers=None, body=None):
    data = json.dumps(body).encode() if body else None
    req  = urllib.request.Request(url, data=data, headers=headers or {}, method=method)
    if data:
        req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, timeout=10) as r:
            return r.status, json.loads(r.read())
    except urllib.error.HTTPError as e:
        try:
            body = json.loads(e.read())
        except Exception:
            body = {"error": e.reason}
        return e.code, body
    except Exception as e:
        return None, str(e)

# ── Pasos ──────────────────────────────────────────────────────────────────────

def paso1_login(backend, usuario, password):
    titulo("PASO 1 — Login en el backend (dolibarr-bff)")
    url = f"{backend}/api/auth/login"
    info(f"POST {url}")
    info(f"Usuario: {usuario}")

    status, data = hacer_request("POST", url, body={"username": usuario, "password": password})

    if status is None:
        err(f"Error de red: {data}")
        return None

    print(f"\n  HTTP {status}")
    print("  " + json.dumps(data, indent=4, ensure_ascii=False).replace("\n", "\n  "))

    token = data.get("token") or data.get("Token")
    if status != 200 or not token:
        err("Login fallido. Comprueba usuario, contraseña y que el backend esté arrancado.")
        return None

    ok("Login correcto. JWT obtenido.")
    return token


def paso2_obtener_token_verifactu(backend, jwt):
    titulo("PASO 2 — Consultar token VeriFactu al backend")
    url = f"{backend}/api/verifactu/token"
    info(f"GET {url}")

    status, data = hacer_request("GET", url, headers={"Authorization": f"Bearer {jwt}"})

    if status is None:
        err(f"Error de red: {data}")
        return None

    print(f"\n  HTTP {status}")
    print("  " + json.dumps(data, indent=4, ensure_ascii=False).replace("\n", "\n  "))

    token = data.get("token") or data.get("Token")
    if status != 200 or not token:
        err("No se pudo obtener el token VeriFactu. ¿Está el certificado registrado?")
        return None

    ok("Token VeriFactu obtenido.")
    return token


def paso3_mostrar_factura():
    titulo("PASO 3 — Factura preparada (formato Dolibarr)")
    info("Misma estructura que el front recibe del backend.")
    print()
    print("  " + json.dumps(FACTURA, indent=4, ensure_ascii=False).replace("\n", "\n  "))


def paso4_enviar_factura(api_url, token):
    titulo("PASO 4 — Enviar factura a VerifactuMidAPI")
    url = f"{api_url}/api/v1/facturas"
    info(f"POST {url}")
    info(f"Token: {token[:40]}…" if len(token) > 40 else f"Token: {token}")

    status, data = hacer_request(
        "POST", url,
        headers={"Authorization": f"Bearer {token}"},
        body=FACTURA
    )

    if status is None:
        err(f"Error de red: {data}")
        return

    print(f"\n  HTTP {status}")

    if data.get("success"):
        ok("Factura procesada correctamente por la API.")
        if data.get("csv"):
            ok(f"Hash de cadena: {data['csv']}")
    else:
        err(f"La API devolvió error: {data.get('error', 'desconocido')}")

# ── Main ───────────────────────────────────────────────────────────────────────

def main():
    parser = argparse.ArgumentParser(description="Demo flujo VeriFactu")
    parser.add_argument("--backend",  default=BACKEND_URL, help="URL del backend dolibarr-bff")
    parser.add_argument("--api",      default=API_URL,     help="URL de VerifactuMidAPI")
    parser.add_argument("--usuario",  default=USUARIO,     help="Usuario del backend")
    parser.add_argument("--password", default=PASSWORD,    help="Contraseña del backend")
    args = parser.parse_args()

    print(_color("\n  VeriFactu Demo — flujo front → API", "1;37"))
    print(_color("  Simula lo que haría el front al pulsar 'Registrar'\n", "2;37"))

    # Paso 1: login → JWT
    jwt = paso1_login(args.backend, args.usuario, args.password)
    if not jwt:
        sys.exit(1)

    # Paso 2: token VeriFactu del backend
    token_verifactu = paso2_obtener_token_verifactu(args.backend, jwt)
    if not token_verifactu:
        sys.exit(1)

    # Paso 3: mostrar la factura
    paso3_mostrar_factura()

    # Paso 4: enviar a la API
    paso4_enviar_factura(args.api, token_verifactu)

    print()


if __name__ == "__main__":
    main()
