"""
ERPNext v16 PostgreSQL GROUP BY fixes.
PostgreSQL requires all non-aggregated SELECT columns in GROUP BY.
MySQL is lenient, ERPNext was built for MySQL.

Run: docker cp fix_pg_groupby.py erpnext-backend-1:/tmp/
     docker exec erpnext-backend-1 bench --site erp.gigafibre.ca execute "exec(open('/tmp/fix_pg_groupby.py').read())"
"""
import os

BENCH = "/home/frappe/frappe-bench/apps/erpnext/erpnext"

patches = []

# ─── 1. controllers/trends.py — based_on_group_by for Customer, Supplier, Item ───
patches.append((
    f"{BENCH}/controllers/trends.py",
    [
        # Customer (non-Quotation): group by needs customer_name, territory
        (
            'based_on_details["based_on_group_by"] = "t1.party_name" if trans == "Quotation" else "t1.customer"',
            'based_on_details["based_on_group_by"] = "t1.party_name, t1.customer_name, t1.territory" if trans == "Quotation" else "t1.customer, t1.customer_name, t1.territory"',
        ),
        # Supplier: group by needs supplier_name, supplier_group
        (
            'based_on_details["based_on_group_by"] = "t1.supplier"',
            'based_on_details["based_on_group_by"] = "t1.supplier, t1.supplier_name, t3.supplier_group"',
        ),
        # Item: group by needs item_name
        (
            'based_on_details["based_on_group_by"] = "t2.item_code"',
            'based_on_details["based_on_group_by"] = "t2.item_code, t2.item_name"',
        ),
    ]
))

# ─── 2. trial_balance.py — account_currency missing from groupby ───
patches.append((
    f"{BENCH}/accounts/report/trial_balance/trial_balance.py",
    [
        (
            ".groupby(closing_balance.account)",
            ".groupby(closing_balance.account, closing_balance.account_currency)",
        ),
    ]
))

# ─── 3. process_period_closing_voucher.py — account_currency ───
patches.append((
    f"{BENCH}/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.py",
    [
        # Add account_currency to groupby after account
        (
            "query = query.groupby(gle.account)",
            "query = query.groupby(gle.account, gle.account_currency)",
        ),
    ]
))

# ─── 4. exchange_rate_revaluation.py — account_currency ───
patches.append((
    f"{BENCH}/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py",
    [
        (
            '.groupby(gle.account, NullIf(gle.party_type, ""), NullIf(gle.party, ""))',
            '.groupby(gle.account, NullIf(gle.party_type, ""), NullIf(gle.party, ""), gle.account_currency)',
        ),
    ]
))

# ─── 5. pos_closing_entry.py — account missing ───
patches.append((
    f"{BENCH}/accounts/doctype/pos_closing_entry/pos_closing_entry.py",
    [
        (
            ".groupby(SalesInvoicePayment.mode_of_payment)",
            ".groupby(SalesInvoicePayment.mode_of_payment, SalesInvoicePayment.account)",
        ),
    ]
))

# ─── 6. voucher_wise_balance.py — voucher_type missing ───
patches.append((
    f"{BENCH}/accounts/report/voucher_wise_balance/voucher_wise_balance.py",
    [
        (
            ".groupby(gle.voucher_no)",
            ".groupby(gle.voucher_no, gle.voucher_type)",
        ),
    ]
))

# ─── 7. total_stock_summary.py — item.description missing ───
patches.append((
    f"{BENCH}/stock/report/total_stock_summary/total_stock_summary.py",
    [
        (
            ".groupby(item.item_code)",
            ".groupby(item.item_code, item.description)",
        ),
    ]
))

# ─── 8. stock_entry.py — job_card_scrap_item missing cols ───
patches.append((
    f"{BENCH}/stock/doctype/stock_entry/stock_entry.py",
    [
        (
            ".groupby(job_card_scrap_item.item_code)",
            ".groupby(job_card_scrap_item.item_code, job_card_scrap_item.item_name, job_card_scrap_item.description, job_card_scrap_item.stock_uom)",
        ),
    ]
))

# ─── Apply patches ───
applied = 0
skipped = 0
errors = 0

for filepath, replacements in patches:
    if not os.path.exists(filepath):
        print(f"SKIP (not found): {filepath}")
        skipped += 1
        continue

    with open(filepath, "r") as f:
        content = f.read()

    modified = False
    for old, new in replacements:
        if old in content:
            content = content.replace(old, new, 1)
            modified = True
            print(f"  PATCHED: {old[:60]}...")
        elif new in content:
            print(f"  ALREADY: {new[:60]}...")
        else:
            print(f"  NOT FOUND in {filepath}: {old[:60]}...")
            errors += 1

    if modified:
        with open(filepath, "w") as f:
            f.write(content)
        applied += 1
        print(f"OK: {filepath}")

print(f"\nDone: {applied} files patched, {skipped} skipped, {errors} not found")
