"""
Fix customer_name on all Sales Invoices + Payment Entries.
During migration, customer_name was set to CUST-xxx instead of the actual name.
This script updates it from the Customer doctype.

Also imports legacy invoice.notes as Comments on Sales Invoice
(e.g. "Renversement de la facture #635893 - Sera facturé dans fiche personnelle")

Run inside erpnext-backend-1:
  /home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/fix_invoice_customer_names.py
"""
import os, sys, time
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)

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

DRY_RUN = False

# ═══════════════════════════════════════════════════════════════
# PHASE 1: Fix customer_name on Sales Invoices
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("PHASE 1: Fix customer_name on Sales Invoices")
print("=" * 60)

t0 = time.time()

# Build customer name map
cust_map = {}
rows = frappe.db.sql('SELECT name, customer_name FROM "tabCustomer"', as_dict=True)
for r in rows:
    cust_map[r['name']] = r['customer_name']
print(f"  Loaded {len(cust_map)} customer names")

# Count broken invoices
broken = frappe.db.sql(
    """SELECT COUNT(*) FROM "tabSales Invoice" WHERE customer_name LIKE 'CUST-%%'"""
)[0][0]
print(f"  Invoices with CUST-xxx name: {broken}")

if not DRY_RUN and broken > 0:
    # Bulk update using a single UPDATE ... FROM
    updated = frappe.db.sql("""
        UPDATE "tabSales Invoice" si
        SET customer_name = c.customer_name
        FROM "tabCustomer" c
        WHERE si.customer = c.name
        AND si.customer_name LIKE 'CUST-%%'
    """)
    frappe.db.commit()
    print(f"  Updated Sales Invoices [{time.time()-t0:.0f}s]")

# ═══════════════════════════════════════════════════════════════
# PHASE 2: Fix customer_name on Payment Entries
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("PHASE 2: Fix customer_name on Payment Entries")
print("=" * 60)

t0 = time.time()
broken_pe = frappe.db.sql(
    """SELECT COUNT(*) FROM "tabPayment Entry" WHERE party_name LIKE 'CUST-%%'"""
)[0][0]
print(f"  Payment Entries with CUST-xxx name: {broken_pe}")

if not DRY_RUN and broken_pe > 0:
    frappe.db.sql("""
        UPDATE "tabPayment Entry" pe
        SET party_name = c.customer_name
        FROM "tabCustomer" c
        WHERE pe.party = c.name
        AND pe.party_name LIKE 'CUST-%%'
    """)
    frappe.db.commit()
    print(f"  Updated Payment Entries [{time.time()-t0:.0f}s]")

# ═══════════════════════════════════════════════════════════════
# PHASE 3: Import legacy invoice notes as Comments
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("PHASE 3: Import invoice notes as Comments")
print("=" * 60)

t0 = time.time()

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

# Get all invoices with notes
with legacy.cursor() as cur:
    cur.execute("""
        SELECT id, notes, account_id, FROM_UNIXTIME(date_orig) as date_created
        FROM invoice
        WHERE notes IS NOT NULL AND notes != '' AND TRIM(notes) != ''
        ORDER BY id
    """)
    noted_invoices = cur.fetchall()

print(f"  Legacy invoices with notes: {len(noted_invoices)}")

# Check which SINV exist in ERPNext
existing_sinv = set()
rows = frappe.db.sql('SELECT name FROM "tabSales Invoice"')
for r in rows:
    existing_sinv.add(r[0])
print(f"  Existing SINVs in ERPNext: {len(existing_sinv)}")

# Check existing comments to avoid duplicates
existing_comments = set()
rows = frappe.db.sql(
    """SELECT reference_name FROM "tabComment"
       WHERE reference_doctype = 'Sales Invoice' AND comment_type = 'Comment'"""
)
for r in rows:
    existing_comments.add(r[0])

imported = 0
skipped = 0
batch = []
now = frappe.utils.now()

for inv in noted_invoices:
    sinv_name = f"SINV-{inv['id']}"
    if sinv_name not in existing_sinv:
        skipped += 1
        continue
    if sinv_name in existing_comments:
        skipped += 1
        continue

    notes = inv['notes'].strip()
    if not notes:
        continue

    creation = str(inv['date_created']) if inv['date_created'] else now

    batch.append({
        'name': f"inv-note-{inv['id']}",
        'comment_type': 'Comment',
        'reference_doctype': 'Sales Invoice',
        'reference_name': sinv_name,
        'content': notes,
        'owner': 'Administrator',
        'comment_by': 'Système legacy',
        'creation': creation,
        'modified': creation,
        'modified_by': 'Administrator',
    })
    imported += 1

print(f"  Notes to import: {imported}, skipped: {skipped}")

if not DRY_RUN and batch:
    # Insert row by row using frappe.db.sql (PostgreSQL compatible)
    CHUNK = 5000
    cols = list(batch[0].keys())
    col_names = ", ".join([f'"{c}"' for c in cols])
    placeholders = ", ".join(["%s"] * len(cols))
    sql = f'INSERT INTO "tabComment" ({col_names}) VALUES ({placeholders}) ON CONFLICT ("name") DO NOTHING'
    for i, row in enumerate(batch):
        vals = tuple(row[c] for c in cols)
        frappe.db.sql(sql, vals, as_dict=False)
        if (i + 1) % CHUNK == 0:
            frappe.db.commit()
            elapsed = time.time() - t0
            rate = (i + 1) / elapsed
            print(f"    Progress: {i+1}/{len(batch)} ({rate:.0f}/s) [{elapsed:.0f}s]")
    frappe.db.commit()
    print(f"  Imported {imported} invoice notes [{time.time()-t0:.0f}s]")

legacy.close()

# ═══════════════════════════════════════════════════════════════
# SUMMARY
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("DONE")
print("=" * 60)
if DRY_RUN:
    print("  ** DRY RUN — no changes made **")
print(f"  Sales Invoices customer_name fixed: {broken}")
print(f"  Payment Entries party_name fixed: {broken_pe}")
print(f"  Invoice notes imported as Comments: {imported}")
