#!/usr/bin/env python
"""
Test the enhanced sales GL posting with COGS entries
"""
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from app.core.database import SessionLocal
from app.services.sales_service import SalesService
from app.models.sales import Invoice, Payment
from app.models.accounting import JournalEntry, AccountingCode
from decimal import Decimal

db = SessionLocal()
sales_service = SalesService(db)

print("=" * 80)
print("TEST: ENHANCED SALES GL POSTING WITH COGS")
print("=" * 80)

# Get a valid user ID for GL posting
from app.models.user import User
test_user = db.query(User).first()
test_user_id = test_user.id if test_user else None

if not test_user_id:
    print("ERROR: No users found in database")
    sys.exit(1)

print(f"Using user: {test_user.username} ({test_user_id})")

# Find an unposted invoice with items
print("\n1. Finding unposted invoice...")
invoice = db.query(Invoice).filter(
    Invoice.posting_status != 'posted',
    Invoice.revenue_account_id.isnot(None),
    Invoice.ar_account_id.isnot(None)
).first()

if not invoice:
    print("   ! No unposted invoices found. Using first invoice as test (will repost).")
    invoice = db.query(Invoice).first()
    if invoice:
        print(f"   Resetting posting status for testing...")
        invoice.posting_status = 'draft'

        # Set GL accounts if missing
        if not invoice.revenue_account_id:
            rev_account = db.query(AccountingCode).filter(
                AccountingCode.code == '4000'  # Sales/Revenue account
            ).first()
            if not rev_account:
                rev_account = db.query(AccountingCode).filter(
                    AccountingCode.account_type == 'Revenue'
                ).first()
            if rev_account:
                invoice.revenue_account_id = rev_account.id
                print(f"     Set revenue account to {rev_account.code}")

        if not invoice.ar_account_id:
            ar_account = db.query(AccountingCode).filter(
                AccountingCode.code == '1200'  # AR account
            ).first()
            if not ar_account:
                ar_account = db.query(AccountingCode).filter(
                    AccountingCode.account_type == 'Asset'
                ).first()
            if ar_account:
                invoice.ar_account_id = ar_account.id
                print(f"     Set AR account to {ar_account.code}")

        db.commit()

if not invoice:
    print("   ERROR: No invoices found in database")
    sys.exit(1)

print(f"   Invoice: {invoice.invoice_number}")
print(f"   Total: {invoice.total_amount}")
print(f"   Items: {len(invoice.invoice_items)}")
print(f"   Status: {invoice.posting_status}")
print(f"   Revenue Account: {invoice.revenue_account_id}")
print(f"   AR Account: {invoice.ar_account_id}")

# Show invoice items
print(f"\n   Invoice Items:")
for item in invoice.invoice_items:
    prod_name = item.product.name if item.product else "Unknown"
    print(f"   - {item.product_id}: {prod_name}")
    print(f"     Qty: {item.quantity}, Price: {item.price}, Total: {item.total}")
    if item.product:
        print(f"     Cost: {item.product.cost_price}, GL Account: {item.product.accounting_code_id}")

# Test posting
print("\n2. Testing post_sale_to_accounting()...")
try:
    result = sales_service.post_sale_to_accounting(invoice.id, user_id=test_user_id)
    print(f"   SUCCESS!")
    print(f"   - Entries created: {result['entries_created']}")
    print(f"   - Journal Entry IDs: {len(result['journal_entry_ids'])}")
    print(f"   - Total amount: {result['total_amount']}")
except Exception as e:
    print(f"   ERROR: {e}")
    import traceback
    traceback.print_exc()
    sys.exit(1)

# Verify GL entries
print("\n3. Verifying GL entries created...")
je_list = db.query(JournalEntry).filter(
    JournalEntry.accounting_entry_id.in_(
        [je_id for je_id in result['journal_entry_ids']]
    )
).all()

print(f"   Total entries: {len(je_list)}")

entry_summary = {}
for je in je_list:
    acc = db.query(AccountingCode).filter(AccountingCode.id == je.accounting_code_id).first()
    if acc:
        acc_name = f"{acc.code} {acc.name}"
    else:
        acc_name = f"Unknown ({je.accounting_code_id})"

    if acc_name not in entry_summary:
        entry_summary[acc_name] = {'debits': Decimal('0'), 'credits': Decimal('0'), 'count': 0}

    entry_summary[acc_name]['debits'] += Decimal(str(je.debit_amount or 0))
    entry_summary[acc_name]['credits'] += Decimal(str(je.credit_amount or 0))
    entry_summary[acc_name]['count'] += 1

print("\n   Entries by Account:")
for acc_name, data in sorted(entry_summary.items()):
    print(f"   - {acc_name}: {data['count']} entries")
    print(f"     Debits: {data['debits']}, Credits: {data['credits']}")

# Verify AR and Revenue entries exist
print("\n4. Verifying required entry types...")
revenue_found = False
ar_found = False
cogs_found = False
inventory_found = False

for je in je_list:
    acc = db.query(AccountingCode).filter(AccountingCode.id == je.accounting_code_id).first()
    if je.debit_amount > 0 and invoice.ar_account_id == je.accounting_code_id:
        ar_found = True
    if je.credit_amount > 0 and invoice.revenue_account_id == je.accounting_code_id:
        revenue_found = True
    if acc and acc.code == '5000':
        cogs_found = True
    if je.credit_amount > 0 and acc and acc.code == '1144':
        inventory_found = True

print(f"   AR entry (Debit): {'FOUND' if ar_found else 'NOT FOUND'}")
print(f"   Revenue entry (Credit): {'FOUND' if revenue_found else 'NOT FOUND'}")
print(f"   COGS entry (Debit): {'FOUND' if cogs_found else 'NOT FOUND'}")
print(f"   Inventory entry (Credit): {'FOUND' if inventory_found else 'NOT FOUND'}")

# Test payment posting
print("\n5. Testing post_sale_payment_to_accounting()...")
payment = db.query(Payment).filter(
    Payment.invoice_id == invoice.id
).first()

if payment:
    print(f"   Found payment: {payment.id}")
    print(f"   Amount: {payment.amount}")
    print(f"   Method: {payment.payment_method}")
    print(f"   Bank Account ID: {payment.bank_account_id}")

    try:
        pmt_result = sales_service.post_sale_payment_to_accounting(payment.id, user_id=test_user_id)
        print(f"   SUCCESS!")
        print(f"   - Entries created: {pmt_result['entries_created']}")
        print(f"   - Journal Entry IDs: {len(pmt_result['journal_entry_ids'])}")
    except Exception as e:
        print(f"   ERROR: {e}")
        import traceback
        traceback.print_exc()
else:
    print("   No payments found for this invoice")

print("\n" + "=" * 80)
print("TEST COMPLETE")
print("=" * 80)

db.close()
