"""
Import employees from legacy staff table into ERPNext Employee doctype.
Run inside erpnext-backend-1:
  /home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/import_employees.py

Maps legacy group_ad → Department, status → Active/Inactive.
Idempotent: deletes existing employees before reimporting.
"""
import frappe
import pymysql
import os
import time
from datetime import datetime

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)

T_TOTAL = time.time()

# ═══════════════════════════════════════════════════════════════
# CONFIG
# ═══════════════════════════════════════════════════════════════
COMPANY = "TARGO"

# Legacy group_ad → ERPNext Department
DEPT_MAP = {
    "admin":        "Management - T",
    "sysadmin":     "Operations - T",
    "tech":         "Operations - T",
    "support":      "Customer Service - T",
    "comptabilite": "Accounts - T",
    "facturation":  "Accounts - T",
    "":             None,
    "none":         None,
}

# Legacy group_ad → ERPNext Designation
DESIG_MAP = {
    "admin":        "Manager",
    "sysadmin":     "Engineer",
    "tech":         "Technician",
    "support":      "Customer Service Representative",
    "comptabilite": "Accountant",
    "facturation":  "Accountant",
}

# ═══════════════════════════════════════════════════════════════
# PHASE 0: Ensure prerequisite records exist
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 0: PREREQUISITES")
print("="*60)

# Gender "Prefer not to say"
if not frappe.db.exists("Gender", "Prefer not to say"):
    frappe.get_doc({"doctype": "Gender", "gender": "Prefer not to say"}).insert()
    frappe.db.commit()
    print("Created Gender: Prefer not to say")

# Designation "Technician" — insert via SQL
for desig_name in ["Technician"]:
    if not frappe.db.exists("Designation", desig_name):
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
        frappe.db.sql("""
            INSERT INTO "tabDesignation" (name, creation, modified, modified_by, owner, docstatus, idx)
            VALUES (%(n)s, %(now)s, %(now)s, 'Administrator', 'Administrator', 0, 0)
        """, {"n": desig_name, "now": now})
        frappe.db.commit()
        print("Created Designation:", desig_name)

# ═══════════════════════════════════════════════════════════════
# PHASE 1: CLEANUP existing employees
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 1: CLEANUP")
print("="*60)

existing = frappe.db.sql('SELECT COUNT(*) FROM "tabEmployee"')[0][0]
if existing > 0:
    frappe.db.sql('DELETE FROM "tabEmployee"')
    frappe.db.commit()
    print("Deleted {} existing employees".format(existing))
else:
    print("No existing employees to delete")

# Reset naming series counter
frappe.db.sql("""
    DELETE FROM "tabSeries" WHERE name = 'HR-EMP-'
""")
frappe.db.commit()

# ═══════════════════════════════════════════════════════════════
# PHASE 2: FETCH legacy staff
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 2: FETCH LEGACY STAFF")
print("="*60)

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

with conn.cursor() as cur:
    cur.execute("""
        SELECT id, status, username, first_name, last_name, email, ext, cell,
               group_ad, date_embauche, fete, matricule_desjardins, ldap_id
        FROM staff ORDER BY id
    """)
    staff = cur.fetchall()

conn.close()
print("Fetched {} staff records".format(len(staff)))

# ═══════════════════════════════════════════════════════════════
# PHASE 3: INSERT employees via bulk SQL
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 3: INSERT EMPLOYEES")
print("="*60)

now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
counter = 0
skipped = 0

for s in staff:
    # Skip system/bot accounts with no real name
    if not s["first_name"] or s["first_name"].strip() == "":
        skipped += 1
        continue

    counter += 1
    emp_name = "HR-EMP-{}".format(counter)
    first_name = (s["first_name"] or "").replace("&#039;", "'").strip()
    last_name = (s["last_name"] or "").replace("&#039;", "'").strip()
    full_name = "{} {}".format(first_name, last_name).strip()

    # Status: legacy 1 = Active, -1 = Inactive/Left
    status = "Active" if s["status"] == 1 else "Left"

    # Department
    group = (s["group_ad"] or "").strip().lower()
    dept = DEPT_MAP.get(group)

    # Designation
    desig = DESIG_MAP.get(group)

    # Date of joining from unix timestamp
    doj = None
    if s["date_embauche"]:
        try:
            ts = int(s["date_embauche"])
            if ts > 0:
                doj = datetime.fromtimestamp(ts).strftime("%Y-%m-%d")
        except (ValueError, OSError):
            pass
    if not doj:
        doj = "2020-01-01"  # placeholder

    # Date of birth from fete (DD|MM or MM|DD format)
    dob = None
    if s["fete"]:
        parts = s["fete"].split("|")
        if len(parts) == 2:
            try:
                day = int(parts[0])
                month = int(parts[1])
                # Format is DD|MM based on sample data (e.g. "06|05" = June 5th)
                # But "30|12" = 30th of December — day|month
                if day > 12:
                    # day is definitely the day
                    dob = "1990-{:02d}-{:02d}".format(month, day)
                elif month > 12:
                    # month field is actually the day
                    dob = "1990-{:02d}-{:02d}".format(day, month)
                else:
                    # Ambiguous — use DD|MM interpretation
                    dob = "1990-{:02d}-{:02d}".format(month, day)
            except (ValueError, IndexError):
                pass
    if not dob:
        dob = "1990-01-01"  # placeholder

    # Email
    email = (s["email"] or "").strip()
    company_email = email if email.endswith("@targointernet.com") else None

    # Cell phone
    cell = (s["cell"] or "").strip()

    # Employee number = legacy staff ID
    emp_number = str(s["id"])

    frappe.db.sql("""
        INSERT INTO "tabEmployee" (
            name, creation, modified, modified_by, owner, docstatus, idx,
            naming_series, first_name, last_name, employee_name,
            gender, date_of_birth, date_of_joining,
            status, company, department, designation,
            employee_number, cell_number, company_email, personal_email,
            prefered_contact_email,
            lft, rgt
        ) VALUES (
            %(name)s, %(now)s, %(now)s, 'Administrator', 'Administrator', 0, 0,
            'HR-EMP-', %(first_name)s, %(last_name)s, %(full_name)s,
            'Prefer not to say', %(dob)s, %(doj)s,
            %(status)s, %(company)s, %(dept)s, %(desig)s,
            %(emp_number)s, %(cell)s, %(company_email)s, %(personal_email)s,
            %(pref_email)s,
            0, 0
        )
    """, {
        "name": emp_name,
        "now": now_str,
        "first_name": first_name,
        "last_name": last_name,
        "full_name": full_name,
        "dob": dob,
        "doj": doj,
        "status": status,
        "company": COMPANY,
        "dept": dept,
        "desig": desig,
        "emp_number": emp_number,
        "cell": cell if cell else None,
        "company_email": company_email,
        "personal_email": email if email and not email.endswith("@targointernet.com") else None,
        "pref_email": "Company Email" if company_email else None,
    })

frappe.db.commit()
print("Inserted {} employees ({} skipped - no name)".format(counter, skipped))

# Set the naming series counter
frappe.db.sql("""
    INSERT INTO "tabSeries" (name, current) VALUES ('HR-EMP-', %(counter)s)
    ON CONFLICT (name) DO UPDATE SET current = %(counter)s
""", {"counter": counter})
frappe.db.commit()

# Rebuild tree (Employee is a tree doctype with lft/rgt)
try:
    frappe.rebuild_tree("Employee", "reports_to")
    print("Rebuilt employee tree")
except Exception as e:
    print("Tree rebuild skipped:", e)

# ═══════════════════════════════════════════════════════════════
# PHASE 4: VERIFY
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 4: VERIFY")
print("="*60)

total = frappe.db.sql('SELECT COUNT(*) FROM "tabEmployee"')[0][0]
active = frappe.db.sql('SELECT COUNT(*) FROM "tabEmployee" WHERE status = %s', ("Active",))[0][0]
left = frappe.db.sql('SELECT COUNT(*) FROM "tabEmployee" WHERE status = %s', ("Left",))[0][0]

print("Total employees: {}".format(total))
print("  Active: {}".format(active))
print("  Left: {}".format(left))

by_dept = frappe.db.sql("""
    SELECT department, COUNT(*) as cnt FROM "tabEmployee"
    GROUP BY department ORDER BY cnt DESC
""", as_dict=True)
print("\nBy department:")
for d in by_dept:
    print("  {}: {}".format(d["department"] or "(none)", d["cnt"]))

# Sample
sample = frappe.db.sql("""
    SELECT name, employee_name, status, department, designation, employee_number, date_of_joining
    FROM "tabEmployee" ORDER BY name LIMIT 10
""", as_dict=True)
print("\nSample:")
for e in sample:
    print("  {} {} [{}] dept={} desig={} legacy_id={} joined={}".format(
        e["name"], e["employee_name"], e["status"],
        e["department"], e["designation"], e["employee_number"], e["date_of_joining"]))

elapsed = time.time() - T_TOTAL
print("\n" + "="*60)
print("DONE in {:.1f}s".format(elapsed))
print("="*60)
