"""
Django management command to setup accounting system
Usage: python manage.py setup_accounting
"""

from django.core.management.base import BaseCommand
from django.db import transaction
from datetime import datetime, timedelta
from decimal import Decimal

from accounting.models import Account, FiscalPeriod
from users.models import CustomUser


class Command(BaseCommand):
    help = 'Setup Chart of Accounts and Fiscal Periods for Haven Grazuri Accounting System'

    def handle(self, *args, **options):
        """Execute the setup"""
        self.stdout.write("\n" + "="*60)
        self.stdout.write("Haven Grazuri Accounting System Setup")
        self.stdout.write("="*60 + "\n")
        
        try:
            with transaction.atomic():
                self.create_chart_of_accounts()
                self.create_fiscal_periods()
                self.print_summary()
            
            self.stdout.write(self.style.SUCCESS('\n✓ Setup completed successfully!\n'))
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'\n✗ Setup failed: {str(e)}\n'))
            raise

    def create_chart_of_accounts(self):
        """Create the Chart of Accounts"""
        self.stdout.write("\n" + "="*60)
        self.stdout.write("Creating Chart of Accounts")
        self.stdout.write("="*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
                self.stdout.write(self.style.SUCCESS(f'  [+] Created: {account.code} - {account.name}'))
            else:
                existing_count += 1
                self.stdout.write(f'  [ ] Exists:  {account.code} - {account.name}')
        
        self.stdout.write(f'\n  Summary: {created_count} created, {existing_count} already existed')

    def create_fiscal_periods(self):
        """Create fiscal periods for current year"""
        self.stdout.write("\n" + "="*60)
        self.stdout.write("Creating Fiscal Periods")
        self.stdout.write("="*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
                self.stdout.write(self.style.SUCCESS(f'  [+] Created: {period.name}'))
            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
                self.stdout.write(self.style.SUCCESS(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
            self.stdout.write(self.style.SUCCESS(f'  [+] Created: {period.name}'))
        else:
            existing_count += 1
        
        self.stdout.write(f'\n  Summary: {created_count} created, {existing_count} already existed')

    def print_summary(self):
        """Print final summary"""
        self.stdout.write("\n" + "="*60)
        self.stdout.write("Setup Complete!")
        self.stdout.write("="*60)
        
        total_accounts = Account.objects.count()
        active_accounts = Account.objects.filter(is_active=True).count()
        total_periods = FiscalPeriod.objects.count()
        
        self.stdout.write(f'\n  Total accounts: {total_accounts}')
        self.stdout.write(f'  Active accounts: {active_accounts}')
        self.stdout.write(f'  Fiscal periods: {total_periods}')
        
        self.stdout.write('\n  Next steps:')
        self.stdout.write('  1. Access: /accounting/dashboard/')
        self.stdout.write('  2. View accounts: /accounting/accounts/')
        self.stdout.write('  3. Configure user permissions')
        self.stdout.write('  4. Test loan integration\n')
