#!/usr/bin/env python3
"""
Fix migration state for production.

The problem: loans.0025_add_grazuri_foreign_key_models tries to CREATE tables
(bureau_records, loan_disbursements, loan_fees, loan_guarantors, loan_statuses)
that already exist in the database from the old Grazuri schema.

The fix: fake that migration (mark it applied without running SQL), then
run all remaining migrations normally.

Run on server: python fix_migrations.py
"""
import os
import sys
import subprocess
from datetime import datetime

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings_production')

try:
    from dotenv import load_dotenv
    load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), '.env'), override=True)
except ImportError:
    pass

import django
django.setup()

from django.db import connection

py = sys.executable

def run(cmd, ignore_errors=False):
    print(f"\n>>> {cmd}")
    result = subprocess.run(cmd, shell=True, text=True, capture_output=True)
    out = (result.stdout + result.stderr).strip()
    if out:
        print(out)
    ok = result.returncode == 0
    print(f"  {'OK' if ok else 'FAILED'} (exit {result.returncode})")
    return ok

print(f"\n{'='*60}")
print(f"  Migration Fix  {datetime.now():%Y-%m-%d %H:%M:%S}")
print(f"{'='*60}")

# ── Step 1: Fake the problematic migration ────────────────────
print("\n[1] Faking loans.0025 (tables already exist in DB)...")

# Check if it's already recorded in django_migrations
with connection.cursor() as c:
    c.execute("""
        SELECT COUNT(*) FROM django_migrations
        WHERE app='loans' AND name='0025_add_grazuri_foreign_key_models'
    """)
    already_faked = c.fetchone()[0] > 0

if already_faked:
    print("  Already marked as applied — skipping")
else:
    run(f"{py} manage.py migrate loans 0025_add_grazuri_foreign_key_models --fake")

# ── Step 2: Run all remaining migrations normally ─────────────
print("\n[2] Running all remaining migrations...")
run(f"{py} manage.py migrate --run-syncdb")

# ── Step 3: Create cache table ────────────────────────────────
print("\n[3] Creating cache table...")
run(f"{py} manage.py createcachetable", ignore_errors=True)

# ── Step 4: Collect static files ─────────────────────────────
print("\n[4] Collecting static files...")
run(f"{py} manage.py collectstatic --noinput", ignore_errors=True)

# ── Step 5: Verify all critical tables ───────────────────────
print("\n[5] Verifying critical tables...")
critical = [
    'django_session',
    'django_migrations',
    'users',
    'loans',
    'utils_systemsetting',
    'utils_notification',
    'auth_permission',
    'django_content_type',
    'cache_table',
]

with connection.cursor() as c:
    c.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE()")
    existing = {r[0].lower() for r in c.fetchall()}

all_ok = True
for table in critical:
    status = "OK     " if table.lower() in existing else "MISSING"
    if table.lower() not in existing:
        all_ok = False
    print(f"  {status}  {table}")

# ── Step 6: Show any remaining unapplied migrations ───────────
print("\n[6] Checking for remaining unapplied migrations...")
result = subprocess.run(
    f"{py} manage.py showmigrations --plan",
    shell=True, text=True, capture_output=True
)
unapplied = [l.strip() for l in result.stdout.splitlines() if l.strip().startswith('[ ]')]
if unapplied:
    print(f"  {len(unapplied)} unapplied migrations remain:")
    for m in unapplied:
        print(f"    {m}")
else:
    print("  All migrations applied")

print(f"\n{'='*60}")
if all_ok:
    print("  SUCCESS — all tables present.")
    print("  Restart your app in cPanel to clear the 500 error.")
else:
    print("  Some tables still missing — check errors above.")
print(f"{'='*60}\n")
