#!/usr/bin/env python3
"""
Patches content_bundle_0.js with two fixes:
  Fix 1 - Handle "X hour/hours" before month parsing (prevents null deliveryTimeDate)
  Fix 2 - Null guard before .getTime() in isItemDeliveryExtended (prevents crash)
"""

import re, sys, shutil
from pathlib import Path

BUNDLE = Path("content_bundle_0.js")

if not BUNDLE.exists():
    print(f"ERROR: {BUNDLE} not found. Run this script from the same directory as the bundle.")
    sys.exit(1)

src = BUNDLE.read_text(encoding="utf-8")
original_src = src
patches_applied = []

# ─────────────────────────────────────────────────────────────────────────────
# FIX 1 — early-return for "X hour/hours" BEFORE the month-recognition block
# ─────────────────────────────────────────────────────────────────────────────
# Strategy: find "Month not recognized" (fallback string in the parser),
# then scan backwards for the nearest altMatch check to anchor our insertion.
# We look for a pattern like:
#   altMatch[2]==="hour"   or   altMatch[2]==="hours"
# already present (means fix was already applied), else we find the block
# that checks the month name and inject before it.

MONTH_NOT_RECOGNIZED = '"Month not recognized"'
HOUR_GUARD_MARKER    = "'hour'"   # presence of this near altMatch means fix 1 already in

# Locate the month-parsing region
mnr_pos = src.find(MONTH_NOT_RECOGNIZED)
if mnr_pos == -1:
    mnr_pos = src.find("Month not recognized")

if mnr_pos == -1:
    print("WARN Fix1: Could not find 'Month not recognized' string. Showing 5 nearby greps instead:")
    for m in re.finditer(r'[Mm]onth', src):
        print(f"  pos {m.start()}: ...{src[max(0,m.start()-40):m.start()+60]}...")
        break
else:
    print(f"OK  Fix1: Found 'Month not recognized' at pos {mnr_pos}")

    # Search 3000 chars back for the altMatch array access pattern
    window = src[max(0, mnr_pos - 3000): mnr_pos]

    # Check if fix already applied
    if HOUR_GUARD_MARKER in window and "same-day" in window:
        print("     Fix1: Already applied — skipping.")
    else:
        # Find the altMatch conditional that starts the month-check block
        # Minified typically looks like:   if(altMatch){  or  altMatch&&
        # We want the last occurrence of altMatch in the window before fallback text
        alt_matches = list(re.finditer(r'if\s*\(\s*altMatch\b', window))
        if not alt_matches:
            # Try looser: just altMatch[
            alt_matches = list(re.finditer(r'altMatch\[', window))

        if not alt_matches:
            print("WARN Fix1: Could not find 'altMatch' reference before 'Month not recognized'.")
            print("     Paste ~200 chars before that string and re-run, or apply Fix 1 manually.")
        else:
            # Take the LAST altMatch reference in the window (closest to the month block)
            last_match = alt_matches[-1]
            insert_abs_pos = max(0, mnr_pos - 3000) + last_match.start()

            # Build the injection snippet (semicolon-safe, minifier-compatible)
            injection = (
                "if(altMatch&&(altMatch[2]==='hour'||altMatch[2]==='hours')){"
                "const deliveryDate=new Date();"
                "deliveryDate.setHours(deliveryDate.getHours()+parseInt(altMatch[1],10));"
                "return deliveryDate;}"
            )

            src = src[:insert_abs_pos] + injection + src[insert_abs_pos:]
            patches_applied.append("Fix 1: hour/hours early-return injected before month-parsing block")
            print(f"     Fix1: Injected at pos {insert_abs_pos}")

# ─────────────────────────────────────────────────────────────────────────────
# FIX 2 — null guard before .getTime() in isItemDeliveryExtended
# ─────────────────────────────────────────────────────────────────────────────
# Look for the pattern:   deliveryTimeDate.getTime()
# inside (or near) isItemDeliveryExtended.
# Replace:  const diff=deliveryTimeDate.getTime()-Date.now()
# With:     if(!deliveryTimeDate)return false;const diff=deliveryTimeDate.getTime()-Date.now()

GETTIME_PAT = re.compile(
    r'(const\s+diff\s*=\s*)(deliveryTimeDate\.getTime\(\))',
    re.ASCII
)

# Also try without `const` (could be var/let or direct assignment)
GETTIME_PAT2 = re.compile(
    r'(?<![a-zA-Z0-9_$])(deliveryTimeDate\.getTime\(\)\s*-\s*Date\.now\(\))',
    re.ASCII
)

m1 = GETTIME_PAT.search(src)
m2 = GETTIME_PAT2.search(src) if not m1 else None

if m1:
    if "if(!deliveryTimeDate)" in src[max(0, m1.start()-60):m1.start()]:
        print("OK  Fix2: Null guard already present — skipping.")
    else:
        replacement = "if(!deliveryTimeDate)return false;" + m1.group(0)
        src = src[:m1.start()] + replacement + src[m1.end():]
        patches_applied.append("Fix 2: null guard added before deliveryTimeDate.getTime()")
        print(f"OK  Fix2: Null guard inserted at pos {m1.start()}")
elif m2:
    if "if(!deliveryTimeDate)" in src[max(0, m2.start()-60):m2.start()]:
        print("OK  Fix2: Null guard already present — skipping.")
    else:
        replacement = "if(!deliveryTimeDate)return false;" + m2.group(1)
        src = src[:m2.start()] + replacement + src[m2.end():]
        patches_applied.append("Fix 2: null guard added before deliveryTimeDate.getTime()")
        print(f"OK  Fix2: Null guard inserted at pos {m2.start()}")
else:
    # Fallback: scan for just .getTime() and show context
    gt_matches = [m for m in re.finditer(r'deliveryTimeDate\.getTime', src)]
    if gt_matches:
        print(f"WARN Fix2: Found {len(gt_matches)} 'deliveryTimeDate.getTime' occurrence(s) but pattern didn't match.")
        for m in gt_matches[:3]:
            ctx = src[max(0,m.start()-80):m.start()+80]
            print(f"  pos {m.start()}: ...{ctx}...")
        print("     Apply Fix 2 manually or share the context above so the script can be updated.")
    else:
        print("WARN Fix2: 'deliveryTimeDate.getTime' not found. Try searching for 'getTime' near 'isItemDeliveryExtended'.")

# ─────────────────────────────────────────────────────────────────────────────
# WRITE OUTPUT
# ─────────────────────────────────────────────────────────────────────────────
if patches_applied:
    # Backup original
    backup = Path("content_bundle_0.js.bak")
    if not backup.exists():
        shutil.copy2(BUNDLE, backup)
        print(f"\nBacked up original to {backup}")

    BUNDLE.write_text(src, encoding="utf-8")
    print(f"\nPatched file written to {BUNDLE}")
    print("\nPatches applied:")
    for p in patches_applied:
        print(f"  ✓ {p}")
else:
    print("\nNo changes written (nothing to patch or all already applied).")

print("\nDone.")
input("\nPress Enter to close...")