"""
Import soumissions (quotes) from legacy as ERPNext Quotation.
Deserializes PHP-serialized materiel/mensuel arrays into Quotation Items.

Run inside erpnext-backend-1:
  /home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/import_soumissions.py
"""
import frappe
import pymysql
import os, sys, time, re
from html import unescape

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
os.chdir("/home/frappe/frappe-bench/sites")
frappe.init(site="erp.gigafibre.ca", sites_path=".")
frappe.connect()
frappe.local.flags.ignore_permissions = True
print("Connected:", frappe.local.site)

legacy = pymysql.connect(
    host="legacy-db", user="facturation", password="***LEGACY-DB-PW-REDACTED***",
    database="gestionclient", cursorclass=pymysql.cursors.DictCursor
)

cust_map = {}
for r in frappe.db.sql('SELECT name, legacy_account_id FROM "tabCustomer" WHERE legacy_account_id > 0', as_dict=True):
    cust_map[int(r['legacy_account_id'])] = r['name']
print(f"  {len(cust_map)} customers mapped")

# Ensure SVC item exists (catch-all for unmapped SKUs)
if not frappe.db.exists("Item", "SVC"):
    frappe.get_doc({"doctype": "Item", "item_code": "SVC", "item_name": "Service",
                    "item_group": "All Item Groups", "stock_uom": "Nos"}).insert()
    frappe.db.commit()
    print("  Created catch-all item SVC")


def parse_php_serialized(data):
    """Simple parser for PHP serialized arrays of items.
    Returns list of dicts with keys: sku, desc, amt, qte, tot"""
    if not data or data in ('a:0:{}', 'N;'):
        return []
    items = []
    # Extract items using regex — handles nested a:N:{...} structures
    # Pattern: s:3:"sku";s:N:"VALUE";...s:4:"desc";s:N:"VALUE";...s:3:"amt";s:N:"VALUE";
    item_pattern = re.compile(
        r's:3:"sku";s:\d+:"([^"]*)";'
        r's:4:"desc";s:\d+:"([^"]*)";'
        r's:3:"amt";s:\d+:"([^"]*)";'
        r's:3:"qte";s:\d+:"([^"]*)";'
        r's:3:"tot";s:\d+:"([^"]*)";'
    )
    for m in item_pattern.finditer(data):
        sku, desc, amt, qte, tot = m.groups()
        desc = unescape(desc).strip()
        try:
            amount = float(tot) if tot else (float(amt) * float(qte) if amt and qte else 0)
            qty = float(qte) if qte else 1
            rate = float(amt) if amt else (amount / qty if qty else 0)
        except ValueError:
            amount = 0
            qty = 1
            rate = 0
        if desc or amount:  # skip empty rows
            items.append({"sku": sku, "desc": desc, "rate": rate, "qty": qty, "amount": amount})
    return items


def parse_date(date_str):
    """Parse dd-mm-yyyy to yyyy-mm-dd"""
    if not date_str:
        return None
    try:
        parts = date_str.strip().split('-')
        if len(parts) == 3:
            return f"{parts[2]}-{parts[1]}-{parts[0]}"
    except Exception:
        pass
    return None


# Load soumissions
print("\n=== Loading legacy soumissions ===")
with legacy.cursor() as cur:
    cur.execute("SELECT * FROM soumission ORDER BY id")
    rows = cur.fetchall()
legacy.close()
print(f"  {len(rows)} soumissions to import")

# Add custom fields BEFORE cleanup check (column must exist first)
for fdef in [
    {"dt": "Quotation", "fieldname": "custom_legacy_soumission_id", "fieldtype": "Int",
     "label": "Legacy Soumission ID", "insert_after": "order_type"},
    {"dt": "Quotation", "fieldname": "custom_po_number", "fieldtype": "Data",
     "label": "PO Number", "insert_after": "custom_legacy_soumission_id"},
]:
    if not frappe.db.exists("Custom Field", {"dt": fdef["dt"], "fieldname": fdef["fieldname"]}):
        frappe.get_doc({"doctype": "Custom Field", **fdef}).insert(ignore_permissions=True)
        frappe.db.commit()
        print(f"  Added custom field {fdef['fieldname']}")

# Clear existing legacy quotations
existing = frappe.db.sql("SELECT COUNT(*) FROM \"tabQuotation\" WHERE custom_legacy_soumission_id > 0")[0][0]
if existing:
    # Delete items first, then quotations
    frappe.db.sql("""
        DELETE FROM "tabQuotation Item"
        WHERE parent IN (SELECT name FROM "tabQuotation" WHERE custom_legacy_soumission_id > 0)
    """)
    frappe.db.sql('DELETE FROM "tabQuotation" WHERE custom_legacy_soumission_id > 0')
    frappe.db.commit()
    print(f"  Cleared {existing} existing legacy Quotations")

T0 = time.time()
created = skipped = empty = 0

for r in rows:
    cust = cust_map.get(r['account_id'])
    if not cust:
        skipped += 1
        continue

    materiel = parse_php_serialized(r.get('materiel') or '')
    mensuel = parse_php_serialized(r.get('mensuel') or '')
    all_items = materiel + mensuel

    if not all_items:
        # Create with single placeholder item
        all_items = [{"sku": "SVC", "desc": (r['name'] or 'Soumission'), "rate": 0, "qty": 1, "amount": 0}]
        empty += 1

    posting_date = parse_date(r.get('date'))

    items = []
    for idx, item in enumerate(all_items):
        items.append({
            "item_code": "SVC",
            "item_name": item['desc'][:140] if item['desc'] else f"Item {idx+1}",
            "description": item['desc'] or '',
            "qty": item['qty'] or 1,
            "rate": item['rate'] or 0,
            "uom": "Nos",
        })

    doc = frappe.get_doc({
        "doctype": "Quotation",
        "quotation_to": "Customer",
        "party_name": cust,
        "transaction_date": posting_date or "2026-01-01",
        "valid_till": posting_date or "2026-01-01",
        "company": "TARGO",
        "currency": "CAD",
        "order_type": "Sales",
        "title": (r['name'] or f"Soumission {r['id']}")[:140],
        "terms": unescape(r.get('text') or ''),
        "custom_legacy_soumission_id": r['id'],
        "custom_po_number": r.get('po') or '',
        "items": items,
    })

    try:
        doc.insert(ignore_if_duplicate=True)
        created += 1
    except Exception as e:
        print(f"  ERR soumission {r['id']}: {str(e)[:80]}")
        skipped += 1

    if created % 100 == 0:
        frappe.db.commit()
        print(f"  [{created}/{len(rows)}] [{time.time()-T0:.0f}s]")

frappe.db.commit()

# ── Verify ──
print(f"\n=== Summary ===")
total = frappe.db.sql('SELECT COUNT(*) FROM "tabQuotation" WHERE custom_legacy_soumission_id > 0')[0][0]
print(f"  Created: {created} Quotations")
print(f"  Empty items (placeholder): {empty}")
print(f"  Skipped: {skipped}")
print(f"  Total: {total}")
print(f"  Time: {time.time()-T0:.0f}s")

frappe.destroy()
print("Done!")
