#!/usr/bin/env python3
import json
import os
import re
import sys

import requests


OLD_URL = "https://cortes-db.edd-os.com.ar"
OLD_EMAIL = "edelmar.edd@gmail.com"
OLD_PASS = "564712564712"


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 patch_record(base, headers, collection, record_id, payload):
    response = requests.patch(base + f"/api/collections/{collection}/records/{record_id}", headers=headers, json=payload, timeout=30)
    if response.status_code >= 300:
        raise RuntimeError(f"patch {collection}/{record_id}: {response.status_code} {response.text[:500]} payload={payload}")
    return response.json()


def legacy_jobs():
    base, headers = auth(OLD_URL, OLD_EMAIL, OLD_PASS)
    state = all_records(base, headers, "state")
    if not state:
        return []
    return state[0].get("jobs") or []


def number_key(value):
    text = str(value or "")
    match = re.search(r"(\d{1,4})", text)
    return int(match.group(1)) if match else None


def veta(value):
    if value in {"ancho", "width"}:
        return "ancho"
    if value in {"alto", "height"}:
        return "alto"
    return "ninguna"


def int_value(value, default=0):
    try:
        return int(value)
    except (TypeError, ValueError):
        return default


def float_value(value, default=0):
    try:
        return float(value)
    except (TypeError, ValueError):
        return default


def main():
    apply = "--apply" in sys.argv
    base, headers = auth(os.environ["PB_URL"], os.environ["PB_ADMIN_EMAIL"], os.environ["PB_ADMIN_PASSWORD"])
    pedidos = all_records(base, headers, "pedidos")
    pedidos_by_num = {int(p["numero"]): p for p in pedidos if p.get("numero") is not None}
    existing_jobs = all_records(base, headers, "corte_jobs")
    existing_legacy_ids = {job.get("legacy_job_id") for job in existing_jobs if job.get("legacy_job_id")}
    jobs = legacy_jobs()

    matches = []
    unmatched = []
    for job in jobs:
        key = number_key(job.get("number"))
        pedido = pedidos_by_num.get(key) if key is not None else None
        if pedido:
            matches.append((job, pedido))
        else:
            unmatched.append(job)

    print(json.dumps({
        "legacy_jobs": len(jobs),
        "matches": len(matches),
        "unmatched": len(unmatched),
        "already_imported": len(existing_legacy_ids),
    }, ensure_ascii=False, indent=2))
    if not apply:
        print("DRY RUN: add --apply to import matched cortes.")
        return

    created_jobs = created_items = skipped = 0
    for job, pedido in matches:
        if job.get("id") in existing_legacy_ids:
            skipped += 1
            continue
        created_job = create_record(base, headers, "corte_jobs", {
            "pedido": pedido["id"],
            "numero": pedido.get("codigo") or str(pedido.get("numero") or job.get("number") or ""),
            "cliente_nombre": "",
            "source": "pedido",
            "legacy_job_id": job.get("id") or "",
            "archived": bool(job.get("archived")),
            "sort_order": 0,
        })
        created_jobs += 1
        all_done = True
        any_started = False
        for index, cut in enumerate(job.get("cuts") or []):
            done = bool(cut.get("done"))
            all_done = all_done and done
            any_started = any_started or done or bool(cut.get("cantoWidthDone")) or bool(cut.get("cantoHeightDone"))
            create_record(base, headers, "corte_items", {
                "job": created_job["id"],
                "legacy_item_id": cut.get("id") or "",
                "cantidad": max(1, int_value(cut.get("quantity"), 1)),
                "ancho": float_value(cut.get("width")),
                "alto": float_value(cut.get("height")),
                "material": str(cut.get("material") or "18b"),
                "color": str(cut.get("colorLabel") or ""),
                "canto_ancho": int_value(cut.get("edgeWidth")),
                "canto_alto": int_value(cut.get("edgeHeight")),
                "veta": veta(cut.get("grainDirection")),
                "nota": str(cut.get("note") or ""),
                "estado": "cortado" if done else "pendiente",
                "canto_ancho_hecho": int_value(cut.get("cantoWidthDone")),
                "canto_alto_hecho": int_value(cut.get("cantoHeightDone")),
                "sort_order": index,
            })
            created_items += 1
        if job.get("cuts"):
            estado = "cortados" if all_done else "en_corte" if any_started else "pendiente"
            patch_record(base, headers, "pedidos", pedido["id"], {"estado_cortes": estado})

    print(json.dumps({
        "created_jobs": created_jobs,
        "created_items": created_items,
        "skipped_existing": skipped,
        "final_corte_jobs": len(all_records(base, headers, "corte_jobs")),
        "final_corte_items": len(all_records(base, headers, "corte_items")),
    }, ensure_ascii=False, indent=2))


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