"""
Analyze pricing cleanup: show catalog price for services, keep rebates as-is,
adjust biggest rebate to absorb the difference when hijack < catalog.

Rules:
  1. Positive products: show MAX(hijack_price, base_price) — catalog or higher
  2. Negative products (rebates): show hijack_price as-is
  3. If hijack_price < base_price on a positive product, the difference
     gets added to the biggest rebate at that delivery address
  4. Total per delivery must stay the same

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

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

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

# ═══════════════════════════════════════════════════════════════
# LOAD LEGACY DATA
# ═══════════════════════════════════════════════════════════════
print("Loading legacy data...")

with conn.cursor() as cur:
    # All active services with product info
    cur.execute("""
        SELECT s.id, s.delivery_id, s.product_id, s.hijack, s.hijack_price, s.hijack_desc,
               p.sku, p.price as base_price, p.category,
               d.account_id
        FROM service s
        JOIN product p ON p.id = s.product_id
        JOIN delivery d ON d.id = s.delivery_id
        WHERE s.status = 1
        ORDER BY s.delivery_id, p.price DESC
    """)
    all_services = cur.fetchall()

conn.close()

print("Active services loaded: {}".format(len(all_services)))

# Group by delivery_id
deliveries = {}
for s in all_services:
    did = s["delivery_id"]
    if did not in deliveries:
        deliveries[did] = []

    base = float(s["base_price"] or 0)
    actual = float(s["hijack_price"]) if s["hijack"] else base
    is_rebate = base < 0  # Product is inherently a rebate (SKU like RAB24M, RAB2X)

    deliveries[did].append({
        "svc_id": s["id"],
        "sku": s["sku"],
        "base_price": base,
        "actual_price": actual,
        "is_rebate": is_rebate,
        "hijack": s["hijack"],
        "hijack_desc": s["hijack_desc"] or "",
        "account_id": s["account_id"],
    })

print("Deliveries with active services: {}".format(len(deliveries)))

# ═══════════════════════════════════════════════════════════════
# APPLY PRICING RULES
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 70)
print("PRICING ANALYSIS")
print("=" * 70)

total_deliveries_affected = 0
total_services_adjusted = 0
adjustments = []  # [(delivery_id, account_id, old_total, new_total, services)]

for did, services in deliveries.items():
    old_total = sum(s["actual_price"] for s in services)

    # Step 1: Determine new display prices
    discount_to_absorb = 0.0
    for s in services:
        if s["is_rebate"]:
            # Rebate product: keep actual price
            s["new_price"] = s["actual_price"]
        else:
            # Positive product
            if s["actual_price"] < s["base_price"]:
                # Hijack made it cheaper → show catalog, track discount
                discount_to_absorb += (s["base_price"] - s["actual_price"])
                s["new_price"] = s["base_price"]
                s["adjusted"] = True
            else:
                # Hijack same or higher → keep actual (custom service)
                s["new_price"] = s["actual_price"]
                s["adjusted"] = False

    # Step 2: Find biggest rebate and add discount_to_absorb to it
    rebate_adjusted = False
    if discount_to_absorb > 0.005:
        # Find the rebate with the most negative price
        rebates = [s for s in services if s["is_rebate"]]
        if rebates:
            biggest_rebate = min(rebates, key=lambda s: s["new_price"])
            biggest_rebate["new_price"] -= discount_to_absorb
            biggest_rebate["absorbed"] = discount_to_absorb
            rebate_adjusted = True
            total_deliveries_affected += 1
        else:
            # No rebate exists — need to create one? Or leave as-is
            # For now, mark as needing attention
            pass

    new_total = sum(s["new_price"] for s in services)

    # Verify totals match
    if abs(old_total - new_total) > 0.02:
        adjustments.append((did, services[0]["account_id"], old_total, new_total, services, "MISMATCH"))
    elif rebate_adjusted:
        adjustments.append((did, services[0]["account_id"], old_total, new_total, services, "OK"))

    for s in services:
        if s.get("adjusted"):
            total_services_adjusted += 1

print("\nDeliveries affected (rebate adjusted): {}".format(total_deliveries_affected))
print("Individual services price-restored to catalog: {}".format(total_services_adjusted))

# Count mismatches
mismatches = [a for a in adjustments if a[5] == "MISMATCH"]
ok_adjustments = [a for a in adjustments if a[5] == "OK"]
print("Clean adjustments (total preserved): {}".format(len(ok_adjustments)))
print("MISMATCHES (total changed): {}".format(len(mismatches)))

# ═══════════════════════════════════════════════════════════════
# SHOW DETAILED EXAMPLES
# ═══════════════════════════════════════════════════════════════

# Find Expro Transit (account 3673) deliveries
expro = [a for a in adjustments if a[1] == 3673]
print("\n" + "=" * 70)
print("EXPRO TRANSIT (account 3673) — {} deliveries affected".format(len(expro)))
print("=" * 70)

for did, acct_id, old_total, new_total, services, status in expro:
    print("\n  Delivery {} — {} [total: {:.2f}]".format(did, status, old_total))
    print("  {:<14} {:>10} {:>10} {:>10}  {}".format(
        "SKU", "BASE", "ACTUAL", "NEW", "NOTE"))
    print("  " + "-" * 66)
    for s in sorted(services, key=lambda x: (x["is_rebate"], -x["new_price"])):
        note = ""
        if s.get("adjusted"):
            note = "← restored to catalog (+{:.2f} to rebate)".format(s["base_price"] - s["actual_price"])
        if s.get("absorbed"):
            note = "← absorbed {:.2f} discount".format(s["absorbed"])

        marker = "  " if not s["is_rebate"] else "    "
        print("  {}{:<12} {:>10.2f} {:>10.2f} {:>10.2f}  {}".format(
            marker, s["sku"], s["base_price"], s["actual_price"], s["new_price"], note))

# ═══════════════════════════════════════════════════════════════
# SHOW OTHER SAMPLE CUSTOMERS
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 70)
print("SAMPLE OTHER CUSTOMERS")
print("=" * 70)

# Get customer names for sample accounts
sample_accts = set()
for a in ok_adjustments[:20]:
    sample_accts.add(a[1])

if sample_accts:
    acct_list = list(sample_accts)[:5]
    for acct_id in acct_list:
        cust = frappe.db.sql("""
            SELECT name, customer_name FROM "tabCustomer"
            WHERE legacy_account_id = %s LIMIT 1
        """, (acct_id,), as_dict=True)
        cust_name = cust[0]["customer_name"] if cust else "account {}".format(acct_id)

        acct_adjustments = [a for a in adjustments if a[1] == acct_id]
        print("\n  {} (account {}) — {} deliveries".format(cust_name, acct_id, len(acct_adjustments)))

        for did, _, old_total, new_total, services, status in acct_adjustments[:2]:
            print("    Delivery {} [total: {:.2f}] {}".format(did, old_total, status))
            for s in sorted(services, key=lambda x: (x["is_rebate"], -x["new_price"])):
                if s.get("adjusted") or s.get("absorbed"):
                    marker = "  " if not s["is_rebate"] else "    "
                    note = ""
                    if s.get("adjusted"):
                        note = "catalog:{:.2f} actual:{:.2f} → NEW:{:.2f}".format(
                            s["base_price"], s["actual_price"], s["new_price"])
                    if s.get("absorbed"):
                        note = "absorbed {:.2f} → NEW:{:.2f}".format(s["absorbed"], s["new_price"])
                    print("      {}{:<12} {}".format(marker, s["sku"], note))

# ═══════════════════════════════════════════════════════════════
# DELIVERIES WITHOUT REBATES (discount but no rebate to absorb)
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 70)
print("PROBLEM CASES: discount but NO rebate to absorb it")
print("=" * 70)

no_rebate_discount = 0
for did, services in deliveries.items():
    has_discount = False
    has_rebate = False
    for s in services:
        if not s["is_rebate"] and s["actual_price"] < s["base_price"] - 0.01:
            has_discount = True
        if s["is_rebate"]:
            has_rebate = True
    if has_discount and not has_rebate:
        no_rebate_discount += 1
        if no_rebate_discount <= 5:
            print("  Delivery {}: services with discount but no rebate product".format(did))
            for s in services:
                if s["actual_price"] < s["base_price"] - 0.01:
                    print("    {} base={:.2f} actual={:.2f} diff={:.2f}".format(
                        s["sku"], s["base_price"], s["actual_price"],
                        s["base_price"] - s["actual_price"]))

print("\nTotal deliveries with discount but no rebate: {}".format(no_rebate_discount))

# ═══════════════════════════════════════════════════════════════
# GLOBAL STATS
# ═══════════════════════════════════════════════════════════════
print("\n" + "=" * 70)
print("GLOBAL SUMMARY")
print("=" * 70)

total_svc = len(all_services)
hijacked = sum(1 for s in all_services if s["hijack"])
hijacked_lower = sum(1 for did, svcs in deliveries.items() for s in svcs
                     if not s["is_rebate"] and s["actual_price"] < s["base_price"] - 0.01)
hijacked_higher = sum(1 for did, svcs in deliveries.items() for s in svcs
                      if not s["is_rebate"] and s["actual_price"] > s["base_price"] + 0.01 and s["hijack"])

print("Total active services: {:,}".format(total_svc))
print("Hijacked (custom price): {:,}".format(hijacked))
print("  ↳ cheaper than catalog: {:,} (restore to catalog + absorb in rebate)".format(hijacked_lower))
print("  ↳ more expensive than catalog: {:,} (keep actual — custom service)".format(hijacked_higher))
print("Deliveries needing rebate adjustment: {:,}".format(total_deliveries_affected))
print("Deliveries with no rebate to absorb: {:,}".format(no_rebate_discount))

print("\n" + "=" * 70)
print("ANALYSIS COMPLETE — no changes made")
print("=" * 70)
