#!/usr/bin/env python3
import argparse
import json
import os
import re
import sys
from pathlib import Path

import requests


def auth(base, email, password):
    base = base.rstrip("/")
    response = requests.post(
        base + "/api/collections/_superusers/auth-with-password",
        json={"identity": email, "password": password},
        timeout=30,
    )
    response.raise_for_status()
    return base, {"Authorization": "Bearer " + response.json()["token"]}


def all_records(base, headers, collection):
    items = []
    page = 1
    while True:
        response = requests.get(
            base + f"/api/collections/{collection}/records",
            headers=headers,
            params={"page": page, "perPage": 200},
            timeout=30,
        )
        response.raise_for_status()
        data = response.json()
        items.extend(data.get("items", []))
        if page >= data.get("totalPages", 1):
            break
        page += 1
    return items


def create_record(base, headers, collection, payload):
    response = requests.post(
        base + f"/api/collections/{collection}/records",
        headers=headers,
        json=payload,
        timeout=30,
    )
    if response.status_code >= 300:
        raise RuntimeError(f"create {collection}: {response.status_code} {response.text[:500]} payload={payload}")
    return response.json()


def parse_date(value):
    if not value:
        return ""
    text = str(value).replace("T", " ").replace("Z", "").split(".")[0]
    if len(text) == 10:
        text += " 12:00:00"
    return f"{text}.000Z"


def order_number(reference):
    match = re.search(r"(\d+)$", str(reference or ""))
    return int(match.group(1)) if match else None


def client_key(name, phone):
    digits = re.sub(r"\D", "", phone or "")
    return digits or (name or "Sin nombre").strip().lower()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--orders-json", required=True)
    parser.add_argument("--delivered", action="store_true")
    parser.add_argument("--apply", action="store_true")
    args = parser.parse_args()

    base, headers = auth(os.environ["PB_URL"], os.environ["PB_ADMIN_EMAIL"], os.environ["PB_ADMIN_PASSWORD"])
    rows = json.loads(Path(args.orders_json).read_text(encoding="utf-8"))

    existing_pedidos = {record.get("codigo"): record for record in all_records(base, headers, "pedidos") if record.get("codigo")}
    existing_clientes = {}
    for cliente in all_records(base, headers, "clientes"):
        existing_clientes[client_key(cliente.get("nombre"), cliente.get("celular"))] = cliente

    refs = [str(row.get("Referencia de la orden") or "").strip() for row in rows]
    duplicates = sorted(ref for ref in refs if ref in existing_pedidos)
    summary = {
        "source_rows": len(rows),
        "existing_duplicates": duplicates,
        "to_create": len(rows) - len(duplicates),
        "total": sum(float(row.get("Total") or 0) for row in rows),
        "saldo": sum(float(row.get("Saldo") or 0) for row in rows),
    }
    print(json.dumps(summary, ensure_ascii=False, indent=2))
    if not args.apply:
        print("DRY RUN: add --apply to import.")
        return

    created_clientes = 0
    created_pedidos = 0
    skipped = 0
    for row in rows:
        reference = str(row.get("Referencia de la orden") or "").strip()
        if reference in existing_pedidos:
            skipped += 1
            continue

        name = str(row.get("Cliente") or "").strip() or "Sin nombre"
        phone = str(row.get("Teléfono") or "").strip()
        key = client_key(name, phone)
        cliente = existing_clientes.get(key)
        if not cliente:
            cliente = create_record(base, headers, "clientes", {
                "nombre": name,
                "celular": phone,
                "direccion": "",
                "notas": "Importado desde Odoo.",
            })
            existing_clientes[key] = cliente
            created_clientes += 1

        total = float(row.get("Total") or 0)
        saldo = float(row.get("Saldo") or 0)
        paid = max(0, total - saldo)
        etapa = "entregado_con_saldo" if args.delivered and saldo > 0 else "entregado_sin_saldo" if args.delivered else "pedido_nuevo"
        pedido = create_record(base, headers, "pedidos", {
            "codigo": reference,
            "numero": order_number(reference),
            "referencia_odoo": reference,
            "cliente": cliente["id"],
            "fecha_creacion": parse_date(row.get("Fecha de la orden")),
            "fecha_entrega_estimada": parse_date(row.get("Fecha esperada")),
            "total": total,
            "pagado": paid,
            "senia": paid,
            "saldo": saldo,
            "estado_pedido": "entregado" if args.delivered else "cargado",
            "estado_cortes": "cortados" if args.delivered else "pendiente",
            "etapa_produccion": etapa,
            "avisado_retiro": bool(args.delivered),
            "hay_que_medir": False,
            "hay_que_enviar": False,
            "descripcion": (
                f"Importado desde Odoo. Referencia: {reference}.\n"
                f"Estado de entrega Odoo: {row.get('Estado de la entrega') or 'sin dato'}.\n"
                f"Etapa Odoo: {row.get('Etapa') or 'sin etapa'}.\n"
                f"Cuaderno: {'sí' if row.get('Cuaderno') else 'no'}."
            ),
        })
        existing_pedidos[reference] = pedido
        created_pedidos += 1

    print(json.dumps({
        "created_clientes": created_clientes,
        "created_pedidos": created_pedidos,
        "skipped_duplicates": skipped,
        "final_pedidos": len(all_records(base, headers, "pedidos")),
        "final_clientes": len(all_records(base, headers, "clientes")),
    }, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    try:
        main()
    except Exception as exc:
        print(f"FATAL: {exc}", file=sys.stderr)
        sys.exit(1)
