"""
add_missing_custom_fields.py — Add all missing custom fields to ERPNext doctypes.

Covers the complete field gap identified in LEGACY-FIELD-GAP-ANALYSIS.md.
Adds ~73 custom fields across Customer, Service Subscription, Service Equipment,
Service Location, and Dispatch Job.

Run inside erpnext-backend-1:
  /home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/add_missing_custom_fields.py
"""
import frappe
import os

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)


def add_custom_fields(doctype, fields):
    """Add a list of custom fields to a doctype, skipping existing ones."""
    count = 0
    for f in fields:
        fieldname = f["fieldname"]
        exists = frappe.db.exists("Custom Field", {"dt": doctype, "fieldname": fieldname})
        if exists:
            continue
        try:
            doc = frappe.get_doc({
                "doctype": "Custom Field",
                "dt": doctype,
                **f,
            })
            doc.insert(ignore_permissions=True)
            count += 1
            print("  + {}.{}".format(doctype, fieldname))
        except Exception as e:
            print("  ! {}.{} — ERROR: {}".format(doctype, fieldname, str(e)[:100]))
    frappe.db.commit()
    return count


# ═══════════════════════════════════════════════════════════════════════════
# 1. CUSTOMER — PPA, Stripe, Termination, VIP, Portal, Marketing
# ═══════════════════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("CUSTOMER — Adding missing fields")
print("=" * 60)

customer_fields = [
    # ── PPA (Pre-Authorized Payment) Section ──
    {"fieldname": "ppa_section", "label": "Paiement pré-autorisé (PPA)", "fieldtype": "Section Break",
     "insert_after": "notes_internal", "collapsible": 1},
    {"fieldname": "ppa_enabled", "label": "PPA activé", "fieldtype": "Check",
     "insert_after": "ppa_section"},
    {"fieldname": "ppa_name", "label": "Nom du payeur", "fieldtype": "Data",
     "insert_after": "ppa_enabled", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_code", "label": "Transit bancaire", "fieldtype": "Data",
     "insert_after": "ppa_name", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_branch", "label": "Succursale", "fieldtype": "Data",
     "insert_after": "ppa_code", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_col_break", "fieldtype": "Column Break",
     "insert_after": "ppa_branch"},
    {"fieldname": "ppa_account", "label": "Numéro de compte", "fieldtype": "Data",
     "insert_after": "ppa_col_break", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_amount", "label": "Montant PPA", "fieldtype": "Currency",
     "insert_after": "ppa_account", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_amount_buffer", "label": "Montant tampon", "fieldtype": "Currency",
     "insert_after": "ppa_amount", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_fixed", "label": "Montant fixe", "fieldtype": "Check",
     "insert_after": "ppa_amount_buffer", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_cc", "label": "PPA par carte de crédit", "fieldtype": "Check",
     "insert_after": "ppa_fixed", "depends_on": "eval:doc.ppa_enabled"},
    {"fieldname": "ppa_all_invoice", "label": "Appliquer à toutes les factures", "fieldtype": "Check",
     "insert_after": "ppa_cc", "depends_on": "eval:doc.ppa_enabled"},

    # ── Stripe Section ──
    {"fieldname": "stripe_section", "label": "Stripe", "fieldtype": "Section Break",
     "insert_after": "ppa_all_invoice", "collapsible": 1},
    {"fieldname": "stripe_customer_id", "label": "Stripe Customer ID", "fieldtype": "Data",
     "insert_after": "stripe_section", "description": "cus_XXXXX"},
    {"fieldname": "stripe_ppa_enabled", "label": "Paiement auto Stripe", "fieldtype": "Check",
     "insert_after": "stripe_customer_id"},

    # ── Flags ──
    {"fieldname": "is_vip", "label": "Client VIP", "fieldtype": "Check",
     "insert_after": "is_bad_payer"},
    {"fieldname": "is_land_owner", "label": "Propriétaire terrain", "fieldtype": "Check",
     "insert_after": "is_vip"},
    {"fieldname": "marketing_optin", "label": "Accepte marketing", "fieldtype": "Check",
     "insert_after": "is_land_owner"},
    {"fieldname": "call_contact", "label": "Contact téléphonique", "fieldtype": "Check",
     "insert_after": "marketing_optin"},

    # ── Termination Section ──
    {"fieldname": "termination_section", "label": "Résiliation", "fieldtype": "Section Break",
     "insert_after": "stripe_ppa_enabled", "collapsible": 1},
    {"fieldname": "terminate_date", "label": "Date résiliation", "fieldtype": "Date",
     "insert_after": "termination_section"},
    {"fieldname": "terminate_reason", "label": "Raison", "fieldtype": "Small Text",
     "insert_after": "terminate_date"},
    {"fieldname": "terminate_col", "fieldtype": "Column Break",
     "insert_after": "terminate_reason"},
    {"fieldname": "terminate_cie", "label": "Compétiteur", "fieldtype": "Data",
     "insert_after": "terminate_col"},
    {"fieldname": "terminate_note", "label": "Notes résiliation", "fieldtype": "Small Text",
     "insert_after": "terminate_cie"},

    # ── Client-visible notes ──
    {"fieldname": "notes_client", "label": "Notes client (visible)", "fieldtype": "Small Text",
     "insert_after": "notes_internal", "description": "Notes visibles par le client"},

    # ── Portal ──
    {"fieldname": "portal_section", "label": "Portail client (legacy)", "fieldtype": "Section Break",
     "insert_after": "terminate_note", "collapsible": 1},
    {"fieldname": "portal_username", "label": "Nom d'utilisateur", "fieldtype": "Data",
     "insert_after": "portal_section"},
    {"fieldname": "portal_password_hash", "label": "Hash mot de passe (MD5)", "fieldtype": "Data",
     "insert_after": "portal_username", "read_only": 1},

    # ── Misc ──
    {"fieldname": "middle_name", "label": "Deuxième prénom", "fieldtype": "Data",
     "insert_after": "customer_name"},
    {"fieldname": "salutation_legacy", "label": "Titre (legacy)", "fieldtype": "Data",
     "insert_after": "middle_name"},
    {"fieldname": "search_keyword", "label": "Mot-clé recherche", "fieldtype": "Data",
     "insert_after": "portal_password_hash"},
]

add_custom_fields("Customer", customer_fields)


# ═══════════════════════════════════════════════════════════════════════════
# 2. SERVICE SUBSCRIPTION — Custom pricing, dates, quotas, IP
# ═══════════════════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("SERVICE SUBSCRIPTION — Adding missing fields")
print("=" * 60)

subscription_fields = [
    # ── Custom pricing ──
    {"fieldname": "custom_pricing_section", "label": "Tarification personnalisée", "fieldtype": "Section Break",
     "insert_after": "notes", "collapsible": 1},
    {"fieldname": "is_custom_pricing", "label": "Prix personnalisé (hijack)", "fieldtype": "Check",
     "insert_after": "custom_pricing_section"},
    {"fieldname": "custom_pricing_desc", "label": "Description prix custom", "fieldtype": "Data",
     "insert_after": "is_custom_pricing", "depends_on": "eval:doc.is_custom_pricing"},
    {"fieldname": "custom_col", "fieldtype": "Column Break",
     "insert_after": "custom_pricing_desc"},
    {"fieldname": "quota_day_gb", "label": "Quota jour (Go)", "fieldtype": "Float",
     "insert_after": "custom_col"},
    {"fieldname": "quota_night_gb", "label": "Quota nuit (Go)", "fieldtype": "Float",
     "insert_after": "quota_day_gb"},

    # ── Extended dates ──
    {"fieldname": "dates_extra_section", "label": "Dates supplémentaires", "fieldtype": "Section Break",
     "insert_after": "quota_night_gb", "collapsible": 1},
    {"fieldname": "date_suspended", "label": "Date suspension", "fieldtype": "Date",
     "insert_after": "dates_extra_section"},
    {"fieldname": "active_until", "label": "Actif jusqu'au", "fieldtype": "Date",
     "insert_after": "date_suspended"},
    {"fieldname": "dates_extra_col", "fieldtype": "Column Break",
     "insert_after": "active_until"},
    {"fieldname": "next_invoice_date", "label": "Prochaine facturation", "fieldtype": "Date",
     "insert_after": "dates_extra_col"},

    # ── Network ──
    {"fieldname": "network_section", "label": "Réseau", "fieldtype": "Section Break",
     "insert_after": "next_invoice_date", "collapsible": 1},
    {"fieldname": "static_ip", "label": "IP fixe", "fieldtype": "Data",
     "insert_after": "network_section"},
    {"fieldname": "forfait_internet", "label": "Forfait internet", "fieldtype": "Check",
     "insert_after": "static_ip"},
    {"fieldname": "radius_consumption", "label": "Consommation RADIUS", "fieldtype": "Data",
     "insert_after": "forfait_internet"},
]

add_custom_fields("Service Subscription", subscription_fields)


# ═══════════════════════════════════════════════════════════════════════════
# 3. SERVICE EQUIPMENT — Management, Provisioning, ACS, IPTV
# ═══════════════════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("SERVICE EQUIPMENT — Adding missing fields")
print("=" * 60)

# Note: Service Equipment is a custom doctype, so we add fields directly
# to the DocType definition (not as Custom Field). We use ALTER TABLE.
# But if it was created via setup_fsm_doctypes.py, we can still use Custom Field pattern.

equipment_fields = [
    # ── Management Access ──
    {"fieldname": "mgmt_section", "label": "Accès de gestion", "fieldtype": "Section Break",
     "insert_after": "login_password", "collapsible": 1},
    {"fieldname": "manage_url", "label": "URL de gestion", "fieldtype": "Data",
     "insert_after": "mgmt_section", "description": "http://172.17.x.x:8080 ou IP simple"},
    {"fieldname": "manage_port", "label": "Port gestion", "fieldtype": "Int",
     "insert_after": "manage_url"},
    {"fieldname": "manage_protocol", "label": "Protocole gestion", "fieldtype": "Select",
     "options": "\nHTTP\nHTTPS\nSSH\nTelnet\nSNMP", "insert_after": "manage_port"},
    {"fieldname": "mgmt_col", "fieldtype": "Column Break",
     "insert_after": "manage_protocol"},
    {"fieldname": "cli_ip", "label": "IP CLI", "fieldtype": "Data",
     "insert_after": "mgmt_col"},
    {"fieldname": "cli_port", "label": "Port CLI", "fieldtype": "Int",
     "insert_after": "cli_ip"},
    {"fieldname": "cli_protocol", "label": "Protocole CLI", "fieldtype": "Select",
     "options": "\nSSH\nTelnet", "insert_after": "cli_port"},

    # ── Device hierarchy ──
    {"fieldname": "parent_device", "label": "Équipement parent", "fieldtype": "Link",
     "options": "Service Equipment", "insert_after": "cli_protocol",
     "description": "ONT parent pour routeurs/décodeurs, ou OLT pour ONTs"},
    {"fieldname": "legacy_category", "label": "Catégorie legacy", "fieldtype": "Data",
     "insert_after": "parent_device", "read_only": 1},
    {"fieldname": "device_name_legacy", "label": "Nom legacy", "fieldtype": "Data",
     "insert_after": "legacy_category", "read_only": 1},

    # ── WiFi Provisioning ──
    {"fieldname": "wifi_section", "label": "WiFi (provisionnement)", "fieldtype": "Section Break",
     "insert_after": "device_name_legacy", "collapsible": 1},
    {"fieldname": "wifi_ssid", "label": "SSID WiFi", "fieldtype": "Data",
     "insert_after": "wifi_section"},
    {"fieldname": "wifi_password", "label": "Mot de passe WiFi", "fieldtype": "Password",
     "insert_after": "wifi_ssid"},
    {"fieldname": "wifi_col", "fieldtype": "Column Break",
     "insert_after": "wifi_password"},
    {"fieldname": "wifi_ssid_5g", "label": "SSID WiFi 5GHz", "fieldtype": "Data",
     "insert_after": "wifi_col", "description": "Si différent du 2.4GHz"},
    {"fieldname": "wifi_enabled", "label": "WiFi activé", "fieldtype": "Check",
     "insert_after": "wifi_ssid_5g", "default": "1"},

    # ── VoIP Provisioning ──
    {"fieldname": "voip_section", "label": "VoIP (provisionnement)", "fieldtype": "Section Break",
     "insert_after": "wifi_enabled", "collapsible": 1},
    {"fieldname": "sip_username", "label": "SIP Username", "fieldtype": "Data",
     "insert_after": "voip_section"},
    {"fieldname": "sip_password", "label": "SIP Password", "fieldtype": "Password",
     "insert_after": "sip_username"},
    {"fieldname": "voip_col", "fieldtype": "Column Break",
     "insert_after": "sip_password"},
    {"fieldname": "sip_line", "label": "Ligne SIP", "fieldtype": "Int",
     "insert_after": "voip_col", "default": "1"},

    # ── GPON / ACS ──
    {"fieldname": "gpon_section", "label": "GPON / ACS", "fieldtype": "Section Break",
     "insert_after": "sip_line", "collapsible": 1},
    {"fieldname": "gpon_serial", "label": "GPON Serial (physique)", "fieldtype": "Data",
     "insert_after": "gpon_section", "description": "RCMG/TPLG sur l'étiquette"},
    {"fieldname": "cwmp_serial", "label": "CWMP Serial (GenieACS)", "fieldtype": "Data",
     "insert_after": "gpon_serial", "description": "Serial interne TR-069"},
    {"fieldname": "acs_device_id", "label": "ACS Device ID", "fieldtype": "Data",
     "insert_after": "cwmp_serial", "description": "ID complet GenieACS/Oktopus"},
    {"fieldname": "gpon_col", "fieldtype": "Column Break",
     "insert_after": "acs_device_id"},
    {"fieldname": "fibre_line_profile", "label": "Line Profile ID", "fieldtype": "Data",
     "insert_after": "gpon_col"},
    {"fieldname": "fibre_service_profile", "label": "Service Profile ID", "fieldtype": "Data",
     "insert_after": "fibre_line_profile"},
    {"fieldname": "acs_last_inform", "label": "Dernier inform ACS", "fieldtype": "Datetime",
     "insert_after": "fibre_service_profile", "read_only": 1},
    {"fieldname": "acs_online", "label": "En ligne (ACS)", "fieldtype": "Check",
     "insert_after": "acs_last_inform", "read_only": 1},
    {"fieldname": "wan_ip", "label": "IP WAN", "fieldtype": "Data",
     "insert_after": "acs_online", "read_only": 1},

    # ── IPTV ──
    {"fieldname": "iptv_section", "label": "IPTV", "fieldtype": "Section Break",
     "insert_after": "wan_ip", "collapsible": 1},
    {"fieldname": "iptv_subscription_id", "label": "Ministra/IPTV Sub ID", "fieldtype": "Data",
     "insert_after": "iptv_section"},
    {"fieldname": "mac_addresses_json", "label": "MACs par interface (JSON)", "fieldtype": "Long Text",
     "insert_after": "iptv_subscription_id", "read_only": 1,
     "description": '{"eth0":"AA:BB:CC:DD:EE:FF","eth1":"..."}'},
]

# For Service Equipment (custom doctype), we need to check if these should be
# Custom Fields or direct DocType field additions.
# Since it was created as custom=1, Custom Fields work.
add_custom_fields("Service Equipment", equipment_fields)


# ═══════════════════════════════════════════════════════════════════════════
# 4. SERVICE LOCATION — Fibre infrastructure, VLANs, legacy IDs
# ═══════════════════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("SERVICE LOCATION — Adding missing fields")
print("=" * 60)

location_fields = [
    # ── OLT / Fibre detail ──
    {"fieldname": "fibre_detail_section", "label": "Détails fibre", "fieldtype": "Section Break",
     "insert_after": "network_notes", "collapsible": 1},
    {"fieldname": "legacy_fibre_id", "label": "Fibre ID (legacy)", "fieldtype": "Int",
     "insert_after": "fibre_detail_section"},
    {"fieldname": "ont_serial", "label": "ONT Serial", "fieldtype": "Data",
     "insert_after": "legacy_fibre_id"},
    {"fieldname": "olt_ip", "label": "OLT IP", "fieldtype": "Data",
     "insert_after": "ont_serial"},
    {"fieldname": "olt_name", "label": "Nom OLT", "fieldtype": "Data",
     "insert_after": "olt_ip"},
    {"fieldname": "fibre_col1", "fieldtype": "Column Break",
     "insert_after": "olt_name"},
    {"fieldname": "ont_id", "label": "ONT ID", "fieldtype": "Int",
     "insert_after": "fibre_col1"},
    {"fieldname": "terrain_type", "label": "Type terrain", "fieldtype": "Data",
     "insert_after": "ont_id"},
    {"fieldname": "fibre_distance_m", "label": "Distance fibre (m)", "fieldtype": "Float",
     "insert_after": "terrain_type"},
    {"fieldname": "fibre_spans", "label": "Nombre de portées", "fieldtype": "Int",
     "insert_after": "fibre_distance_m"},
    {"fieldname": "install_time_estimate", "label": "Temps d'installation estimé", "fieldtype": "Data",
     "insert_after": "fibre_spans"},

    # ── VLANs (individual, replacing concatenated network_id) ──
    {"fieldname": "vlan_section", "label": "VLANs", "fieldtype": "Section Break",
     "insert_after": "install_time_estimate", "collapsible": 1},
    {"fieldname": "vlan_manage", "label": "VLAN Gestion", "fieldtype": "Int",
     "insert_after": "vlan_section"},
    {"fieldname": "vlan_internet", "label": "VLAN Internet", "fieldtype": "Int",
     "insert_after": "vlan_manage"},
    {"fieldname": "vlan_col", "fieldtype": "Column Break",
     "insert_after": "vlan_internet"},
    {"fieldname": "vlan_telephone", "label": "VLAN Téléphone", "fieldtype": "Int",
     "insert_after": "vlan_col"},
    {"fieldname": "vlan_tv", "label": "VLAN Télévision", "fieldtype": "Int",
     "insert_after": "vlan_telephone"},

    # ── Building / Apartment ──
    {"fieldname": "building_section", "label": "Immeuble", "fieldtype": "Section Break",
     "insert_after": "vlan_tv", "collapsible": 1},
    {"fieldname": "address_line_2", "label": "Adresse ligne 2", "fieldtype": "Data",
     "insert_after": "building_section"},
    {"fieldname": "apartment_number", "label": "Numéro d'appartement", "fieldtype": "Data",
     "insert_after": "address_line_2"},
    {"fieldname": "is_apartment", "label": "Est un appartement", "fieldtype": "Check",
     "insert_after": "apartment_number"},
    {"fieldname": "apartment_building_id", "label": "ID immeuble", "fieldtype": "Data",
     "insert_after": "is_apartment"},
    {"fieldname": "box_not_installed", "label": "Boîtier pas installé", "fieldtype": "Check",
     "insert_after": "apartment_building_id"},

    # ── Legacy service IDs (for cross-reference) ──
    {"fieldname": "legacy_ids_section", "label": "IDs legacy (référence)", "fieldtype": "Section Break",
     "insert_after": "box_not_installed", "collapsible": 1, "hidden": 1},
    {"fieldname": "manage_service_id", "label": "Service gestion ID", "fieldtype": "Int",
     "insert_after": "legacy_ids_section"},
    {"fieldname": "internet_service_id", "label": "Service internet ID", "fieldtype": "Int",
     "insert_after": "manage_service_id"},
    {"fieldname": "telephone_service_id", "label": "Service téléphone ID", "fieldtype": "Int",
     "insert_after": "internet_service_id"},
    {"fieldname": "tv_service_id", "label": "Service TV ID", "fieldtype": "Int",
     "insert_after": "telephone_service_id"},
    {"fieldname": "placemarks_id", "label": "Placemarks ID", "fieldtype": "Data",
     "insert_after": "tv_service_id"},
    {"fieldname": "delivery_notes", "label": "Notes adresse", "fieldtype": "Small Text",
     "insert_after": "access_notes"},
]

add_custom_fields("Service Location", location_fields)


# ═══════════════════════════════════════════════════════════════════════════
# 5. DISPATCH JOB — Second tech + time tracking
# ═══════════════════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("DISPATCH JOB — Adding missing fields")
print("=" * 60)

dispatch_fields = [
    {"fieldname": "second_technician", "label": "Deuxième technicien", "fieldtype": "Data",
     "insert_after": "actual_end"},
    {"fieldname": "tech1_arrival", "label": "Arrivée tech 1", "fieldtype": "Datetime",
     "insert_after": "second_technician"},
    {"fieldname": "tech1_departure", "label": "Départ tech 1", "fieldtype": "Datetime",
     "insert_after": "tech1_arrival"},
    {"fieldname": "tech2_arrival", "label": "Arrivée tech 2", "fieldtype": "Datetime",
     "insert_after": "tech1_departure"},
    {"fieldname": "tech2_departure", "label": "Départ tech 2", "fieldtype": "Datetime",
     "insert_after": "tech2_arrival"},
]

add_custom_fields("Dispatch Job", dispatch_fields)


# ═══════════════════════════════════════════════════════════════════════════
# DONE
# ═══════════════════════════════════════════════════════════════════════════
print("\n" + "=" * 60)
print("ALL CUSTOM FIELDS ADDED")
print("=" * 60)
print("Next steps:")
print("  1. Run migrate_missing_data.py to populate the new fields")
print("  2. Run migrate_provisioning_data.py for WiFi/VoIP from GenieACS")
