#!/usr/bin/env python3
"""
Correct misposted inventory journal entries.

Moves entries from wrong account (1400 Work in Process) to correct product accounts (like 1144 Merchandise Inventory).
"""

import sys
from decimal import Decimal

sys.path.insert(0, '/dev/cnperp-dimensions')

from app.core.database import SessionLocal, engine
from app.models.accounting import AccountingCode, JournalEntry, AccountingEntry
from app.models.purchases import Purchase, PurchaseItem
from app.models.inventory import Product
from app.services.accounting_service import AccountingService
from sqlalchemy import text

def get_correct_account_for_item(item):
    """Get the correct GL account for a purchase item"""
    if not item.product or not item.product.accounting_code_id:
        return None
    return item.product.accounting_code_id

def fix_misposted_entries():
    """Fix inventory entries that were posted to wrong account"""
    db = SessionLocal()

    print("=" * 70)
    print("CORRECTING MISPOSTED INVENTORY ENTRIES")
    print("=" * 70)
    print()

    # Get the wrong account (1400 Work in Process)
    wrong_account = db.query(AccountingCode).filter(AccountingCode.code == '1400').first()
    if not wrong_account:
        print("ERROR: Account 1400 not found")
        db.close()
        return 1

    # Get the correct account (1144 Merchandise Inventory)
    correct_account = db.query(AccountingCode).filter(AccountingCode.code == '1144').first()
    if not correct_account:
        print("ERROR: Account 1144 not found")
        db.close()
        return 1

    print(f"Wrong Account: {wrong_account.code} ({wrong_account.name})")
    print(f"  Current Balance: {wrong_account.balance}")
    print()
    print(f"Correct Account: {correct_account.code} ({correct_account.name})")
    print(f"  Current Balance: {correct_account.balance}")
    print()

    # Find all inventory debit entries on account 1400
    with engine.connect() as conn:
        result = conn.execute(text("""
            SELECT
                je.id,
                je.purchase_id,
                je.debit_amount,
                je.credit_amount,
                ae.id as entry_id
            FROM journal_entries je
            JOIN accounting_entries ae ON je.accounting_entry_id = ae.id
            WHERE je.accounting_code_id = :acc_id
            AND je.debit_amount > 0
            AND ae.status = 'posted'
            ORDER BY je.created_at
        """), {"acc_id": wrong_account.id})

        wrong_entries = result.fetchall()

    print(f"Found {len(wrong_entries)} inventory entries on account 1400 to fix")
    print()

    if len(wrong_entries) == 0:
        print("No entries to fix!")
        db.close()
        return 0

    # Move each entry to the correct account
    total_moved = Decimal('0')
    for entry_id, purchase_id, debit, credit, ae_id in wrong_entries:
        if not purchase_id:
            print(f"⚠ Skipping entry {entry_id} - no purchase_id")
            continue

        # Get the purchase and its first item to determine correct account
        purchase = db.query(Purchase).filter(Purchase.id == purchase_id).first()
        if not purchase or not purchase.purchase_items:
            print(f"⚠ Skipping entry {entry_id} - no purchase items")
            continue

        default_correct_id = correct_account.id  # Use 1144 as default

        # Update the journal entry to correct account
        je = db.query(JournalEntry).filter(JournalEntry.id == entry_id).first()
        if je:
            old_code = je.accounting_code.code
            je.accounting_code_id = default_correct_id
            total_moved += debit

            print(f"✓ Moved {debit} from {old_code} to {correct_account.code}")

    db.commit()

    print()
    print(f"Total moved: {total_moved}")
    print()

    # Recalculate balances
    print("Recalculating account balances...")
    accounting_service = AccountingService(db)
    accounting_service.update_account_balance(wrong_account.id)
    accounting_service.update_account_balance(correct_account.id)

    db.commit()

    # Show updated balances
    db.refresh(wrong_account)
    db.refresh(correct_account)

    print()
    print("Updated Balances:")
    print(f"  {wrong_account.code}: {wrong_account.balance}")
    print(f"  {correct_account.code}: {correct_account.balance}")
    print()

    db.close()
    return 0

def main():
    print("\n")
    result = fix_misposted_entries()

    if result == 0:
        print("=" * 70)
        print("CORRECTION COMPLETE")
        print("=" * 70)
        print()
        print("Inventory accounts are now correctly updated:")
        print("  - Account 1144 (Merchandise Inventory) shows actual stock value")
        print("  - Account 1400 (Work in Process) no longer contains inventory")
        print()

    return result

if __name__ == "__main__":
    try:
        sys.exit(main())
    except Exception as e:
        print(f"\nERROR: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
