"""
Import VoIP lines from legacy: pbx + phone_addr (911) + phone_provisioning (ATA).
Creates VoIP Line records linked to Customer + Service Location.

Run inside erpnext-backend-1:
  /home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/import_voip_lines.py
"""
import frappe
import pymysql
import os, sys, time

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
)

# Build mappings
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")

loc_map = {}
for r in frappe.db.sql('SELECT name, legacy_delivery_id FROM "tabService Location" WHERE legacy_delivery_id > 0', as_dict=True):
    loc_map[int(r['legacy_delivery_id'])] = r['name']
print(f"  {len(loc_map)} locations mapped")

sub_map = {}
for r in frappe.db.sql('SELECT name, legacy_service_id FROM "tabService Subscription" WHERE legacy_service_id > 0', as_dict=True):
    sub_map[int(r['legacy_service_id'])] = r['name']
print(f"  {len(sub_map)} subscriptions mapped")

# ── Load all 3 legacy tables ──
print("\n=== Loading legacy VoIP data ===")

with legacy.cursor() as cur:
    # PBX lines
    cur.execute("SELECT * FROM pbx ORDER BY id")
    pbx_rows = cur.fetchall()
    print(f"  {len(pbx_rows)} PBX lines")

    # 911 addresses indexed by (account_id, phone)
    cur.execute("SELECT * FROM phone_addr")
    e911_rows = cur.fetchall()
    e911_map = {}
    for r in e911_rows:
        key = (r['account_id'], r['phone'])
        e911_map[key] = r
    print(f"  {len(e911_rows)} 911 addresses ({len(e911_map)} unique)")

    # ATA provisioning indexed by (account_id, phone)
    cur.execute("SELECT * FROM phone_provisioning")
    prov_rows = cur.fetchall()
    prov_map = {}
    for r in prov_rows:
        key = (r['account_id'], r['phone'])
        prov_map[key] = r
    print(f"  {len(prov_rows)} ATA provisioning records")

legacy.close()

# Clear existing
existing = frappe.db.sql('SELECT COUNT(*) FROM "tabVoIP Line"')[0][0]
if existing:
    frappe.db.sql('DELETE FROM "tabVoIP Line"')
    frappe.db.commit()
    print(f"  Cleared {existing} existing VoIP Lines")

# ── Import PBX lines with matched 911 + ATA ──
print("\n=== Importing VoIP Lines ===")
T0 = time.time()
created = skipped = 0
with_911 = without_911 = 0

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

    loc = loc_map.get(pbx['delivery_id'], '')
    sub = sub_map.get(pbx['service_id'], '')
    phone = pbx['phone']

    # Match 911 address
    e911 = e911_map.get((pbx['account_id'], phone), {})
    if e911:
        with_911 += 1
    else:
        without_911 += 1

    # Match ATA provisioning
    prov = prov_map.get((pbx['account_id'], phone), {})

    # Format DID as xxx-xxx-xxxx if 10 digits
    did = phone
    if len(did) == 10:
        did = f"{did[:3]}-{did[3:6]}-{did[6:]}"

    doc = frappe.get_doc({
        "doctype": "VoIP Line",
        "did": did,
        "customer": cust,
        "service_location": loc,
        "subscription": sub,
        "status": "Active",

        # SIP config
        "caller_id": (pbx.get('name') or '').strip(),
        "sip_password": pbx.get('password') or '',
        "extension": pbx.get('int_code') or '',
        "sip_context": pbx.get('user_context') or '',
        "max_calls": pbx.get('max_calls') or 2,
        "call_timeout": pbx.get('call_timeout') or 30,
        "language": pbx.get('language') or 'fr',
        "country_whitelist": pbx.get('country_whitelist') or '',

        # Voicemail
        "voicemail_enabled": 1 if pbx.get('has_vm') else 0,
        "vm_password": pbx.get('vm_password') or '',
        "vm_email": pbx.get('vm_email') or '',
        "vm_keep_msg": 1 if pbx.get('keep_msg') else 0,
        "vm_disk_quota": pbx.get('vm_disk_quota') or 180,

        # 911 address
        "e911_first_name": e911.get('first_name', ''),
        "e911_last_name": e911.get('last_name', ''),
        "e911_street_number": e911.get('street_number', ''),
        "e911_apt": e911.get('apt', ''),
        "e911_street_name": e911.get('street_name', ''),
        "e911_city": e911.get('city', ''),
        "e911_state": e911.get('state', ''),
        "e911_zip": e911.get('zip', ''),
        "e911_cauca_code": e911.get('code_cauca', ''),
        "e911_class": e911.get('class_service', 'RES'),
        "e911_enhanced": 1 if e911.get('enhanced_capable') == 'Y' else 0,
        "e911_synced": 1 if e911 else 0,
        "e911_info": e911.get('info', ''),

        # ATA
        "ata_model": prov.get('app', ''),
        "ata_mac": prov.get('mac', ''),
        "ata_password": prov.get('password', ''),
        "international_enabled": 1 if prov.get('internationnal') else 0,

        # Legacy refs
        "legacy_pbx_id": pbx['id'],
        "legacy_account_id": pbx['account_id'],
        "legacy_delivery_id": pbx.get('delivery_id') or 0,
        "legacy_service_id": pbx.get('service_id') or 0,
    })
    try:
        doc.insert(ignore_if_duplicate=True)
        created += 1
    except Exception as e:
        print(f"  ERR PBX {pbx['id']} DID {did}: {str(e)[:80]}")
        frappe.db.rollback()
        skipped += 1

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

frappe.db.commit()

# ── Import orphan 911 addresses (no PBX line) ──
print("\n=== Importing orphan 911 addresses ===")
orphan_count = 0
pbx_phones = {(r['account_id'], r['phone']) for r in pbx_rows}

for key, e911 in e911_map.items():
    if key in pbx_phones:
        continue  # already imported with PBX line

    cust = cust_map.get(e911['account_id'])
    if not cust:
        continue

    phone = e911['phone']
    did = phone
    if len(did) == 10:
        did = f"{did[:3]}-{did[3:6]}-{did[6:]}"

    doc = frappe.get_doc({
        "doctype": "VoIP Line",
        "did": did,
        "customer": cust,
        "status": "Inactive",
        "caller_id": f"{e911.get('first_name', '')} {e911.get('last_name', '')}".strip(),

        # 911 only
        "e911_first_name": e911.get('first_name', ''),
        "e911_last_name": e911.get('last_name', ''),
        "e911_street_number": e911.get('street_number', ''),
        "e911_apt": e911.get('apt', ''),
        "e911_street_name": e911.get('street_name', ''),
        "e911_city": e911.get('city', ''),
        "e911_state": e911.get('state', ''),
        "e911_zip": e911.get('zip', ''),
        "e911_cauca_code": e911.get('code_cauca', ''),
        "e911_class": e911.get('class_service', 'RES'),
        "e911_enhanced": 1 if e911.get('enhanced_capable') == 'Y' else 0,
        "e911_synced": 1,  # was synced when line was active
        "e911_info": e911.get('info', ''),

        "legacy_account_id": e911['account_id'],
    })
    try:
        doc.insert(ignore_if_duplicate=True)
        orphan_count += 1
    except Exception as e:
        if "Duplicate" not in str(e):
            print(f"  WARN: DID {did} — {str(e)[:60]}")

frappe.db.commit()
print(f"  {orphan_count} orphan 911 lines created")

# ── Verify ──
print(f"\n=== Summary ===")
total = frappe.db.sql('SELECT COUNT(*) FROM "tabVoIP Line"')[0][0]
dist = frappe.db.sql('SELECT status, COUNT(*) FROM "tabVoIP Line" GROUP BY status')
for r in dist:
    print(f"  {r[0]:15s} {r[1]}")
print(f"  With 911 address: {with_911}")
print(f"  Without 911: {without_911}")
print(f"  Orphan 911 (inactive): {orphan_count}")
print(f"  Total: {total} VoIP Lines")
print(f"  Skipped (no customer): {skipped}")
print(f"  Time: {time.time()-T0:.0f}s")

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