"""
Haven Grazuri Accounting System Setup
Simple script to create Chart of Accounts and Fiscal Periods

Run this AFTER migrations:
1. python manage.py makemigrations accounting
2. python manage.py migrate
3. python setup_accounting.py
"""

import os
import django
from datetime import datetime, timedelta
from decimal import Decimal

# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
django.setup()

from accounting.models import Account, FiscalPeriod
from users.models import CustomUser

def create_chart_of_accounts():
    """Create the Chart of Accounts"""
    print("\n" + "="*60)
    print("Creating Chart of Accounts")
    print("="*60 + "\n")
    
    # Get system user
    system_user = CustomUser.objects.filter(role='admin').first()
    
    # Define accounts
    accounts_data = [
        # ASSETS (202xxx)
        {'code': '202001', 'name': 'Loan Portfolio - Principal', 'account_type': 'asset', 'subtype': 'loan_portfolio', 
         'description': 'Outstanding principal balance of all active loans', 'is_system_account': True},
        {'code': '202002', 'name': 'Accrued Interest Receivable', 'account_type': 'asset', 'subtype': 'current_asset',
         'description': 'Interest earned but not yet collected', 'is_system_account': True},
        {'code': '202003', 'name': 'Cash on Hand', 'account_type': 'asset', 'subtype': 'current_asset',
         'description': 'Physical cash in branches', 'is_system_account': True},
        {'code': '202004', 'name': 'Bank Account - Main', 'account_type': 'asset', 'subtype': 'current_asset',
         'description': 'Main operating bank account', 'is_system_account': True},
        {'code': '202005', 'name': 'M-Pesa Account', 'account_type': 'asset', 'subtype': 'current_asset',
         'description': 'M-Pesa business account balance', 'is_system_account': True},
        {'code': '202006', 'name': 'Allowance for Loan Losses', 'account_type': 'asset', 'subtype': 'loan_portfolio',
         'description': 'Reserve for expected loan defaults (contra-asset)', 'is_system_account': True},
        {'code': '202007', 'name': 'Office Equipment', 'account_type': 'asset', 'subtype': 'fixed_asset',
         'description': 'Computers, furniture, and office equipment', 'is_system_account': False},
        {'code': '202008', 'name': 'Accumulated Depreciation - Equipment', 'account_type': 'asset', 'subtype': 'fixed_asset',
         'description': 'Accumulated depreciation on equipment (contra-asset)', 'is_system_account': False},
        
        # LIABILITIES (302xxx)
        {'code': '302001', 'name': 'Client Savings Deposits', 'account_type': 'liability', 'subtype': 'client_savings',
         'description': 'Savings deposits from microfinance clients', 'is_system_account': True},
        {'code': '302002', 'name': 'Loan Payable - Bank', 'account_type': 'liability', 'subtype': 'borrowings',
         'description': 'Loans borrowed from financial institutions', 'is_system_account': False},
        {'code': '302003', 'name': 'Accrued Expenses Payable', 'account_type': 'liability', 'subtype': 'current_liability',
         'description': 'Expenses incurred but not yet paid', 'is_system_account': True},
        {'code': '302004', 'name': 'Interest Payable', 'account_type': 'liability', 'subtype': 'current_liability',
         'description': 'Interest owed on borrowed funds', 'is_system_account': False},
        
        # EQUITY (320xxx)
        {'code': '320001', 'name': 'Share Capital', 'account_type': 'equity', 'subtype': None,
         'description': 'Owner investment in the institution', 'is_system_account': True},
        {'code': '320002', 'name': 'Retained Earnings', 'account_type': 'equity', 'subtype': None,
         'description': 'Accumulated profits retained in the business', 'is_system_account': True},
        {'code': '320003', 'name': 'Current Year Earnings', 'account_type': 'equity', 'subtype': None,
         'description': 'Net income for the current fiscal year', 'is_system_account': True},
        
        # INCOME (401xxx)
        {'code': '401001', 'name': 'Interest Income - Loans', 'account_type': 'income', 'subtype': 'interest_income',
         'description': 'Interest earned from loan products', 'is_system_account': True},
        {'code': '401002', 'name': 'Fee Income - Processing Fees', 'account_type': 'income', 'subtype': 'fee_income',
         'description': 'Loan processing and application fees', 'is_system_account': True},
        {'code': '401003', 'name': 'Fee Income - Late Payment Penalties', 'account_type': 'income', 'subtype': 'fee_income',
         'description': 'Penalties charged on late loan payments', 'is_system_account': True},
        {'code': '401004', 'name': 'Other Income', 'account_type': 'income', 'subtype': 'other_income',
         'description': 'Miscellaneous income sources', 'is_system_account': False},
        
        # EXPENSES (501xxx)
        {'code': '501001', 'name': 'Salaries and Wages', 'account_type': 'expense', 'subtype': 'staff_costs',
         'description': 'Employee salaries and wages', 'is_system_account': True},
        {'code': '501002', 'name': 'Rent Expense', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Office and branch rent payments', 'is_system_account': False},
        {'code': '501003', 'name': 'Utilities Expense', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Electricity, water, and internet expenses', 'is_system_account': False},
        {'code': '501004', 'name': 'Marketing and Advertising', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Marketing and promotional expenses', 'is_system_account': False},
        {'code': '501005', 'name': 'Office Supplies', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Stationery and office supply expenses', 'is_system_account': False},
        {'code': '501006', 'name': 'Transportation Expense', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Vehicle fuel and transportation costs', 'is_system_account': False},
        {'code': '501007', 'name': 'Loan Loss Provision Expense', 'account_type': 'expense', 'subtype': 'loan_loss_provision',
         'description': 'Expense for expected loan defaults', 'is_system_account': True},
        {'code': '501008', 'name': 'Depreciation Expense', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Depreciation of fixed assets', 'is_system_account': False},
        {'code': '501009', 'name': 'Bank Charges', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Banking fees and charges', 'is_system_account': False},
        {'code': '501010', 'name': 'Professional Fees', 'account_type': 'expense', 'subtype': 'operating_expense',
         'description': 'Legal, accounting, and consulting fees', 'is_system_account': False},
    ]
    
    created_count = 0
    existing_count = 0
    
    for account_data in accounts_data:
        account, created = Account.objects.get_or_create(
            code=account_data['code'],
            defaults={
                'name': account_data['name'],
                'account_type': account_data['account_type'],
                'subtype': account_data['subtype'],
                'description': account_data['description'],
                'is_system_account': account_data['is_system_account'],
                'is_active': True,
                'created_by': system_user
            }
        )
        
        if created:
            created_count += 1
            print(f'[+] Created: {account.code} - {account.name}')
        else:
            existing_count += 1
            print(f'[ ] Exists:  {account.code} - {account.name}')
    
    print(f'\nSummary:')
    print(f'  Created: {created_count} accounts')
    print(f'  Already existed: {existing_count} accounts')
    print(f'  Total: {created_count + existing_count} accounts')

def create_fiscal_periods():
    """Create fiscal periods for current year"""
    print("\n" + "="*60)
    print("Creating Fiscal Periods")
    print("="*60 + "\n")
    
    year = datetime.now().year
    created_count = 0
    existing_count = 0
    
    # Create monthly periods
    for month in range(1, 13):
        start_date = datetime(year, month, 1).date()
        
        # Get last day of month
        if month == 12:
            end_date = datetime(year, 12, 31).date()
        else:
            end_date = (datetime(year, month + 1, 1) - timedelta(days=1)).date()
        
        period_name = start_date.strftime('%B %Y')
        
        period, created = FiscalPeriod.objects.get_or_create(
            start_date=start_date,
            end_date=end_date,
            defaults={
                'name': period_name,
                'period_type': 'monthly',
                'status': 'open'
            }
        )
        
        if created:
            created_count += 1
            print(f'[+] Created: {period.name} ({period.start_date} to {period.end_date})')
        else:
            existing_count += 1
    
    # Create quarterly periods
    quarters = [
        {'name': f'Q1 {year}', 'start': datetime(year, 1, 1), 'end': datetime(year, 3, 31)},
        {'name': f'Q2 {year}', 'start': datetime(year, 4, 1), 'end': datetime(year, 6, 30)},
        {'name': f'Q3 {year}', 'start': datetime(year, 7, 1), 'end': datetime(year, 9, 30)},
        {'name': f'Q4 {year}', 'start': datetime(year, 10, 1), 'end': datetime(year, 12, 31)},
    ]
    
    for quarter in quarters:
        period, created = FiscalPeriod.objects.get_or_create(
            name=quarter['name'],
            period_type='quarterly',
            defaults={
                'start_date': quarter['start'].date(),
                'end_date': quarter['end'].date(),
                'status': 'open'
            }
        )
        
        if created:
            created_count += 1
            print(f'[+] Created: {period.name}')
        else:
            existing_count += 1
    
    # Create annual period
    period, created = FiscalPeriod.objects.get_or_create(
        name=f'FY {year}',
        period_type='annual',
        defaults={
            'start_date': datetime(year, 1, 1).date(),
            'end_date': datetime(year, 12, 31).date(),
            'status': 'open'
        }
    )
    
    if created:
        created_count += 1
        print(f'[+] Created: {period.name}')
    else:
        existing_count += 1
    
    print(f'\nSummary:')
    print(f'  Created: {created_count} periods')
    print(f'  Already existed: {existing_count} periods')
    print(f'  Total: {created_count + existing_count} periods')

def main():
    """Main setup function"""
    print("\n" + "="*60)
    print("Haven Grazuri Accounting System Setup")
    print("="*60)
    
    try:
        # Create Chart of Accounts
        create_chart_of_accounts()
        
        # Create Fiscal Periods
        create_fiscal_periods()
        
        # Summary
        print("\n" + "="*60)
        print("Setup Complete!")
        print("="*60)
        print(f"\nAccounts created: {Account.objects.count()}")
        print(f"Fiscal periods created: {FiscalPeriod.objects.count()}")
        print(f"Active accounts: {Account.objects.filter(is_active=True).count()}")
        
        print("\nNext steps:")
        print("1. Access accounting dashboard: /accounting/dashboard/")
        print("2. View Chart of Accounts: /accounting/accounts/")
        print("3. Configure user permissions")
        print("4. Test loan integration")
        print("")
        
    except Exception as e:
        print(f"\nERROR: {str(e)}")
        import traceback
        traceback.print_exc()
        return 1
    
    return 0

if __name__ == '__main__':
    exit(main())
