"""
Import additional customer details from legacy DB into ERPNext.

Adds custom fields and populates:
  - invoice_delivery_method: Email/Paper/Both
  - is_commercial: Commercial account flag
  - is_bad_payer: Mauvais payeur flag
  - tax_category_legacy: Tax group
  - contact_name_legacy: Contact person
  - tel_home/tel_office/cell: Phone numbers
  - mandataire: Authorized representative
  - exclude_fees: Frais exclusion flag
  - notes_internal: Internal notes (misc)
  - date_created_legacy: Account creation date

Run inside erpnext-backend-1:
  /home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/import_customer_details.py
"""
import frappe
import pymysql
import os
from datetime import datetime, timezone

os.chdir("/home/frappe/frappe-bench/sites")
frappe.init(site="erp.gigafibre.ca", sites_path=".")
frappe.connect()
print("Connected:", frappe.local.site)

# ═══════════════════════════════════════════════════════════════
# STEP 1: Create custom fields on Customer
# ═══════════════════════════════════════════════════════════════
print("Creating custom fields on Customer...")

CUSTOM_FIELDS = [
    {"fieldname": "billing_section", "label": "Facturation", "fieldtype": "Section Break", "insert_after": "legacy_section"},
    {"fieldname": "invoice_delivery_method", "label": "Envoi facture", "fieldtype": "Select", "options": "\nEmail\nPapier\nEmail + Papier", "insert_after": "billing_section"},
    {"fieldname": "is_commercial", "label": "Compte commercial", "fieldtype": "Check", "insert_after": "invoice_delivery_method"},
    {"fieldname": "is_bad_payer", "label": "Mauvais payeur", "fieldtype": "Check", "insert_after": "is_commercial"},
    {"fieldname": "exclude_fees", "label": "Exclure frais", "fieldtype": "Check", "insert_after": "is_bad_payer"},
    {"fieldname": "billing_col_break", "label": "", "fieldtype": "Column Break", "insert_after": "exclude_fees"},
    {"fieldname": "tax_category_legacy", "label": "Groupe taxe", "fieldtype": "Select", "options": "\nFederal + Provincial (9.5%)\nFederal seulement\nExempté", "insert_after": "billing_col_break"},
    {"fieldname": "contact_section", "label": "Contact détaillé", "fieldtype": "Section Break", "insert_after": "tax_category_legacy"},
    {"fieldname": "contact_name_legacy", "label": "Contact", "fieldtype": "Data", "insert_after": "contact_section"},
    {"fieldname": "mandataire", "label": "Mandataire", "fieldtype": "Data", "insert_after": "contact_name_legacy"},
    {"fieldname": "tel_home", "label": "Téléphone maison", "fieldtype": "Data", "insert_after": "mandataire"},
    {"fieldname": "contact_col_break", "label": "", "fieldtype": "Column Break", "insert_after": "tel_home"},
    {"fieldname": "tel_office", "label": "Téléphone bureau", "fieldtype": "Data", "insert_after": "contact_col_break"},
    {"fieldname": "cell_phone", "label": "Cellulaire", "fieldtype": "Data", "insert_after": "tel_office"},
    {"fieldname": "fax", "label": "Fax", "fieldtype": "Data", "insert_after": "cell_phone"},
    {"fieldname": "notes_section", "label": "Notes", "fieldtype": "Section Break", "insert_after": "fax"},
    {"fieldname": "notes_internal", "label": "Notes internes", "fieldtype": "Small Text", "insert_after": "notes_section"},
    {"fieldname": "email_billing", "label": "Email facturation", "fieldtype": "Data", "insert_after": "notes_internal"},
    {"fieldname": "email_publipostage", "label": "Email publipostage", "fieldtype": "Data", "insert_after": "email_billing"},
    {"fieldname": "date_created_legacy", "label": "Date création (legacy)", "fieldtype": "Date", "insert_after": "email_publipostage"},
]

for cf in CUSTOM_FIELDS:
    existing = frappe.db.exists("Custom Field", {"dt": "Customer", "fieldname": cf["fieldname"]})
    if existing:
        print("  {} — already exists".format(cf["fieldname"]))
        continue
    try:
        doc = frappe.get_doc({
            "doctype": "Custom Field",
            "dt": "Customer",
            **cf,
        })
        doc.insert(ignore_permissions=True)
        print("  {} — created".format(cf["fieldname"]))
    except Exception as e:
        print("  {} — ERR: {}".format(cf["fieldname"], str(e)[:80]))

frappe.db.commit()
print("Custom fields done.")

# ═══════════════════════════════════════════════════════════════
# STEP 2: Load legacy data
# ═══════════════════════════════════════════════════════════════
print("\nLoading legacy data...")
conn = pymysql.connect(
    host="legacy-db", user="facturation", password="***LEGACY-DB-PW-REDACTED***",
    database="gestionclient", cursorclass=pymysql.cursors.DictCursor
)
with conn.cursor() as cur:
    cur.execute("""
        SELECT id, customer_id, invoice_delivery, commercial, mauvais_payeur,
               tax_group, contact, mandataire, tel_home, tel_office, cell, fax,
               misc, email, email_autre, date_orig, frais, ppa, notes_client,
               address1, address2, city, state, zip
        FROM account
        WHERE status = 1
    """)
    accounts = cur.fetchall()
conn.close()
print("Active legacy accounts: {}".format(len(accounts)))

# Customer mapping
cust_map = {}
custs = frappe.db.sql('SELECT name, legacy_account_id FROM "tabCustomer" WHERE legacy_account_id IS NOT NULL AND legacy_account_id > 0', as_dict=True)
for c in custs:
    cust_map[c["legacy_account_id"]] = c["name"]
print("Customer mapping: {}".format(len(cust_map)))

# ═══════════════════════════════════════════════════════════════
# STEP 3: Update customers
# ═══════════════════════════════════════════════════════════════
INVOICE_DELIVERY = {1: "Email", 2: "Papier", 3: "Email + Papier"}
TAX_GROUP = {1: "Federal + Provincial (9.5%)", 2: "Federal seulement", 3: "Exempté"}

def ts_to_date(ts):
    if not ts or ts <= 0:
        return None
    try:
        return datetime.fromtimestamp(ts, tz=timezone.utc).strftime("%Y-%m-%d")
    except (ValueError, OSError):
        return None

print("\nUpdating customers...")
updated = 0
skipped = 0
errors = 0

for a in accounts:
    acct_id = a["id"]
    cust_name = cust_map.get(acct_id)
    if not cust_name:
        skipped += 1
        continue

    updates = {}
    if a["invoice_delivery"]:
        updates["invoice_delivery_method"] = INVOICE_DELIVERY.get(a["invoice_delivery"], "")
    if a["commercial"]:
        updates["is_commercial"] = 1
    if a["mauvais_payeur"]:
        updates["is_bad_payer"] = 1
    if a["frais"]:
        updates["exclude_fees"] = 1
    if a["tax_group"]:
        updates["tax_category_legacy"] = TAX_GROUP.get(a["tax_group"], "")
    if a["contact"]:
        updates["contact_name_legacy"] = a["contact"]
    if a["mandataire"]:
        updates["mandataire"] = a["mandataire"]
    if a["tel_home"]:
        updates["tel_home"] = a["tel_home"]
    if a["tel_office"]:
        updates["tel_office"] = a["tel_office"]
    if a["cell"]:
        updates["cell_phone"] = a["cell"]
    if a["fax"]:
        updates["fax"] = a["fax"]
    if a["misc"]:
        updates["notes_internal"] = a["misc"]
    if a["email"]:
        updates["email_billing"] = a["email"]
    if a["email_autre"]:
        updates["email_publipostage"] = a["email_autre"]
    created = ts_to_date(a["date_orig"])
    if created:
        updates["date_created_legacy"] = created

    if not updates:
        continue

    # Truncate long values for Data fields (varchar 140)
    for field in ["contact_name_legacy", "mandataire", "tel_home", "tel_office",
                  "cell_phone", "fax", "email_billing", "email_publipostage"]:
        if field in updates and updates[field] and len(str(updates[field])) > 140:
            updates[field] = str(updates[field])[:140]

    # Build SET clause
    set_parts = []
    values = []
    for field, val in updates.items():
        set_parts.append('"{}" = %s'.format(field))
        values.append(val)
    values.append(cust_name)

    try:
        frappe.db.sql(
            'UPDATE "tabCustomer" SET {} WHERE name = %s'.format(", ".join(set_parts)),
            values
        )
        updated += 1
    except Exception as e:
        errors += 1
        if errors <= 5:
            print("  ERR {}: {}".format(cust_name, str(e)[:100]))
        frappe.db.rollback()

    if updated % 1000 == 0:
        frappe.db.commit()
        print("  Progress: {}/{}".format(updated, len(accounts)))

frappe.db.commit()
print("\nUpdated: {} customers".format(updated))
print("Skipped (no mapping): {}".format(skipped))

print("\n" + "=" * 70)
print("DONE")
print("=" * 70)
