#!/usr/bin/env python
"""
Enhance Sales GL Posting to include:
1. Inventory posting (COGS Debit + Inventory Credit using product-assigned accounts)
2. Payment posting (Bank/Cash Debit + AR Credit)
3. VAT posting to correct accounts
4. Bank account selection based on payment method
"""
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.models.sales import Sale, SaleItem, Invoice, InvoiceItem, Payment
from app.models.accounting import AccountingCode, JournalEntry, AccountingEntry
from app.models.inventory import Product
from app.models.banking import BankAccount
from decimal import Decimal
from datetime import datetime, date

db = SessionLocal()

print("=" * 80)
print("ENHANCED SALES GL POSTING SERVICE")
print("=" * 80)

print("""
This script will enhance the sales GL posting to:

1. INVENTORY POSTING (per sale item):
   - Debit: COGS account (Cost of Goods Sold account TBD)
   - Credit: Product-assigned inventory account (e.g., 1144 Merchandise Inventory)
   - Amount: Cost price × Quantity

2. PAYMENT POSTING (on payment receipt):
   - Debit: Bank/Cash account (from payment_method + bank_account_id)
   - Credit: Accounts Receivable (from invoice.ar_account_id)
   - Amount: Payment amount

3. VAT POSTING:
   - Debit: VAT Input/Output accounts (for sales, post Output VAT)
   - Credit: Output VAT Payable (from sale.output_vat_account_id)
   - Amount: Total VAT amount

IMPLEMENTATION PLAN:
""")

# 1. Check for COGS account
print("\n1. Checking for COGS (Cost of Goods Sold) account...")
cogs_account = db.query(AccountingCode).filter(
    AccountingCode.name.ilike('%cost%goods%') |
    AccountingCode.code.in_(['5000', '5100', '5200', '5010'])
).first()

if cogs_account:
    print(f"   Found: {cogs_account.code} - {cogs_account.name}")
else:
    print("   ! No COGS account found. Need to configure one.")
    print("   Suggested: Create account code 5000 (Cost of Goods Sold)")

# 2. Check GL account settings on products
print("\n2. Checking products with GL account assignments...")
products_with_gl = db.query(Product).filter(
    Product.accounting_code_id.isnot(None),
    Product.quantity > 0
).all()

print(f"   Products with GL account assignments: {len(products_with_gl)}")
if products_with_gl:
    for prod in products_with_gl[:3]:
        acc = db.query(AccountingCode).filter(
            AccountingCode.id == prod.accounting_code_id
        ).first()
        if acc:
            print(f"     - {prod.name} ({prod.sku}): Account {acc.code} ({acc.name})")

# 3. Check bank accounts configured
print("\n3. Checking bank accounts...")
bank_accounts = db.query(BankAccount).all()
print(f"   Total bank accounts configured: {len(bank_accounts)}")
for bank in bank_accounts[:3]:
    print(f"     - {bank.name} ({bank.account_number}): GL {bank.accounting_code_id}")

# 4. Check invoices with payment data
print("\n4. Checking invoices with payments...")
invoices_with_payments = db.query(Invoice).join(Payment).distinct().all()
print(f"   Invoices with payments: {len(invoices_with_payments)}")
if invoices_with_payments:
    for inv in invoices_with_payments[:2]:
        payments = db.query(Payment).filter(Payment.invoice_id == inv.id).all()
        total_paid = sum(p.amount for p in payments)
        print(f"     - Invoice {inv.invoice_number}: {len(payments)} payments, Total: {total_paid:,.2f}")
        for pmt in payments[:1]:
            print(f"       • Payment: {pmt.amount:,.2f} via {pmt.payment_method}")

# 5. Identify requirements
print("\n5. REQUIREMENTS FOR COMPLETE SALES GL POSTING:")
print("""
   a) COGS Account:
      - Must be created if not exists (e.g., 5000 - Cost of Goods Sold)
      - Will be debited on sales for inventory cost

   b) Product GL Accounts:
      - Already assigned to accounting_code_id
      - Will be credited when inventory is sold (reducing asset value)

   c) Bank Accounts:
      - Must have GL account mapping (accounting_code_id)
      - Linked to payment method (cash, bank transfer, card, etc.)
      - Will be debited when payments are received

   d) Payment Processing:
      - When payment is posted, create AR Debit + Bank Credit entries
      - Use bank_account_id from payment record to determine GL account

   e) VAT Handling:
      - Output VAT (for sales) - credit Output VAT Payable account
      - Already defined on Sale.output_vat_account_id
""")

print("\n" + "=" * 80)
print("NEXT STEPS:")
print("=" * 80)
print("""
1. Create COGS account (5000) if not exists
2. Update SalesService.post_sale_to_accounting() to:
   - Iterate through invoice items
   - For each item, post COGS Debit + Inventory Credit
   - Use product.accounting_code_id for inventory credit
3. Create new method: post_sale_payment_to_accounting() to:
   - Debit bank account (from payment.bank_account_id)
   - Credit AR account (from invoice.ar_account_id)
   - Called when payment is received
4. Update post_sale_to_accounting() to include VAT posting:
   - Debit Sales account (revenue or receivable)
   - Credit Output VAT account (sale.output_vat_account_id)
""")

db.close()

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