from flask import Blueprint, render_template, request, jsonify
from flask_login import login_required, current_user
from app import db
from app.models import Expense, Category
from sqlalchemy import func, extract
from datetime import datetime, timedelta
from collections import defaultdict

bp = Blueprint('main', __name__)

@bp.route('/')
def index():
    if current_user.is_authenticated:
        return render_template('dashboard.html')
    return render_template('landing.html')


@bp.route('/dashboard')
@login_required
def dashboard():
    return render_template('dashboard.html')


@bp.route('/transactions')
@login_required
def transactions():
    return render_template('transactions.html')


@bp.route('/reports')
@login_required
def reports():
    return render_template('reports.html')


@bp.route('/settings')
@login_required
def settings():
    return render_template('settings.html')


@bp.route('/documents')
@login_required
def documents():
    return render_template('documents.html')


@bp.route('/admin')
@login_required
def admin():
    if not current_user.is_admin:
        return render_template('404.html'), 404
    return render_template('admin.html')


@bp.route('/api/dashboard-stats')
@login_required
def dashboard_stats():
    now = datetime.utcnow()
    
    # Current month stats
    current_month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    
    # Previous month stats
    if now.month == 1:
        prev_month_start = now.replace(year=now.year-1, month=12, day=1)
    else:
        prev_month_start = current_month_start.replace(month=current_month_start.month-1)
    
    # Total spent this month (all currencies - show user's preferred currency)
    current_month_expenses = Expense.query.filter(
        Expense.user_id == current_user.id,
        Expense.date >= current_month_start
    ).all()
    current_month_total = sum(exp.amount for exp in current_month_expenses)
    
    # Previous month total
    prev_month_expenses = Expense.query.filter(
        Expense.user_id == current_user.id,
        Expense.date >= prev_month_start,
        Expense.date < current_month_start
    ).all()
    prev_month_total = sum(exp.amount for exp in prev_month_expenses)
    
    # Calculate percentage change
    if prev_month_total > 0:
        percent_change = ((current_month_total - prev_month_total) / prev_month_total) * 100
    else:
        percent_change = 100 if current_month_total > 0 else 0
    
    # Active categories
    active_categories = Category.query.filter_by(user_id=current_user.id).count()
    
    # Total transactions this month
    total_transactions = Expense.query.filter(
        Expense.user_id == current_user.id,
        Expense.date >= current_month_start
    ).count()
    
    # Category breakdown for entire current year (all currencies)
    current_year_start = now.replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
    category_stats = db.session.query(
        Category.id,
        Category.name,
        Category.color,
        func.sum(Expense.amount).label('total'),
        func.count(Expense.id).label('count')
    ).join(Expense).filter(
        Expense.user_id == current_user.id,
        Expense.date >= current_year_start
    ).group_by(Category.id).order_by(Category.display_order, Category.created_at).all()
    
    # Monthly breakdown (all 12 months of current year)
    monthly_data = []
    for month_num in range(1, 13):
        month_start = now.replace(month=month_num, day=1, hour=0, minute=0, second=0, microsecond=0)
        if month_num == 12:
            month_end = now.replace(year=now.year+1, month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
        else:
            month_end = now.replace(month=month_num+1, day=1, hour=0, minute=0, second=0, microsecond=0)
        
        month_expenses = Expense.query.filter(
            Expense.user_id == current_user.id,
            Expense.date >= month_start,
            Expense.date < month_end
        ).all()
        month_total = sum(exp.amount for exp in month_expenses)
        
        monthly_data.append({
            'month': month_start.strftime('%b'),
            'total': float(month_total)
        })
    
    return jsonify({
        'total_spent': float(current_month_total),
        'percent_change': round(percent_change, 1),
        'active_categories': active_categories,
        'total_transactions': total_transactions,
        'currency': current_user.currency,
        'category_breakdown': [
            {'id': stat[0], 'name': stat[1], 'color': stat[2], 'total': float(stat[3]), 'count': stat[4]}
            for stat in category_stats
        ],
        'monthly_data': monthly_data
    })


@bp.route('/api/recent-transactions')
@login_required
def recent_transactions():
    limit = request.args.get('limit', 10, type=int)
    
    expenses = Expense.query.filter_by(user_id=current_user.id)\
        .order_by(Expense.date.desc())\
        .limit(limit)\
        .all()
    
    return jsonify({
        'transactions': [expense.to_dict() for expense in expenses]
    })


@bp.route('/api/reports-stats')
@login_required
def reports_stats():
    """
    Generate comprehensive financial reports
    Security: Only returns data for current_user (enforced by user_id filter)
    """
    period = request.args.get('period', '30')  # days
    category_filter = request.args.get('category_id', type=int)
    
    try:
        days = int(period)
    except ValueError:
        days = 30
    
    now = datetime.utcnow()
    period_start = now - timedelta(days=days)
    
    # Query with security filter
    query = Expense.query.filter(
        Expense.user_id == current_user.id,
        Expense.date >= period_start
    )
    
    if category_filter:
        query = query.filter_by(category_id=category_filter)
    
    expenses = query.all()
    
    # Total spent in period (all currencies)
    total_spent = sum(exp.amount for exp in expenses)
    
    # Previous period comparison
    prev_period_start = period_start - timedelta(days=days)
    prev_expenses = Expense.query.filter(
        Expense.user_id == current_user.id,
        Expense.date >= prev_period_start,
        Expense.date < period_start
    ).all()
    prev_total = sum(exp.amount for exp in prev_expenses)
    
    percent_change = 0
    if prev_total > 0:
        percent_change = ((total_spent - prev_total) / prev_total) * 100
    elif total_spent > 0:
        percent_change = 100
    
    # Top category (all currencies)
    category_totals = {}
    for exp in expenses:
        cat_name = exp.category.name
        category_totals[cat_name] = category_totals.get(cat_name, 0) + exp.amount
    
    top_category = max(category_totals.items(), key=lambda x: x[1]) if category_totals else ('None', 0)
    
    # Average daily spending
    avg_daily = total_spent / days if days > 0 else 0
    prev_avg_daily = prev_total / days if days > 0 else 0
    avg_change = 0
    if prev_avg_daily > 0:
        avg_change = ((avg_daily - prev_avg_daily) / prev_avg_daily) * 100
    elif avg_daily > 0:
        avg_change = 100
    
    # Savings rate calculation based on monthly budget
    if current_user.monthly_budget and current_user.monthly_budget > 0:
        savings_amount = current_user.monthly_budget - total_spent
        savings_rate = (savings_amount / current_user.monthly_budget) * 100
        savings_rate = max(0, min(100, savings_rate))  # Clamp between 0-100%
    else:
        savings_rate = 0
    
    # Category breakdown for pie chart
    category_breakdown = []
    for cat_name, amount in sorted(category_totals.items(), key=lambda x: x[1], reverse=True):
        category = Category.query.filter_by(user_id=current_user.id, name=cat_name).first()
        if category:
            percentage = (amount / total_spent * 100) if total_spent > 0 else 0
            category_breakdown.append({
                'name': cat_name,
                'color': category.color,
                'amount': float(amount),
                'percentage': round(percentage, 1)
            })
    
    # Daily spending trend (last 30 days)
    daily_trend = []
    for i in range(min(30, days)):
        day_date = now - timedelta(days=i)
        day_start = day_date.replace(hour=0, minute=0, second=0, microsecond=0)
        day_end = day_start + timedelta(days=1)
        
        day_expenses = Expense.query.filter(
            Expense.user_id == current_user.id,
            Expense.date >= day_start,
            Expense.date < day_end
        ).all()
        day_total = sum(exp.amount for exp in day_expenses)
        
        daily_trend.insert(0, {
            'date': day_date.strftime('%d %b'),
            'amount': float(day_total)
        })
    
    # Monthly comparison (all 12 months of current year, all currencies)
    monthly_comparison = []
    current_year = now.year
    for month in range(1, 13):
        month_start = datetime(current_year, month, 1)
        if month == 12:
            month_end = datetime(current_year + 1, 1, 1)
        else:
            month_end = datetime(current_year, month + 1, 1)
        
        month_expenses = Expense.query.filter(
            Expense.user_id == current_user.id,
            Expense.date >= month_start,
            Expense.date < month_end
        ).all()
        month_total = sum(exp.amount for exp in month_expenses)
        
        monthly_comparison.append({
            'month': month_start.strftime('%b'),
            'amount': float(month_total)
        })
    
    return jsonify({
        'total_spent': float(total_spent),
        'percent_change': round(percent_change, 1),
        'top_category': {'name': top_category[0], 'amount': float(top_category[1])},
        'avg_daily': float(avg_daily),
        'avg_daily_change': round(avg_change, 1),
        'savings_rate': savings_rate,
        'category_breakdown': category_breakdown,
        'daily_trend': daily_trend,
        'monthly_comparison': monthly_comparison,
        'currency': current_user.currency,
        'period_days': days
    })


@bp.route('/api/smart-recommendations')
@login_required
def smart_recommendations():
    """
    Generate smart financial recommendations based on user spending patterns
    Security: Only returns recommendations for current_user
    """
    now = datetime.utcnow()
    
    # Get data for last 30 and 60 days for comparison
    period_30 = now - timedelta(days=30)
    period_60 = now - timedelta(days=60)
    period_30_start = period_60
    
    # Current period expenses (all currencies)
    current_expenses = Expense.query.filter(
        Expense.user_id == current_user.id,
        Expense.date >= period_30
    ).all()
    
    # Previous period expenses (all currencies)
    previous_expenses = Expense.query.filter(
        Expense.user_id == current_user.id,
        Expense.date >= period_60,
        Expense.date < period_30
    ).all()
    
    current_total = sum(exp.amount for exp in current_expenses)
    previous_total = sum(exp.amount for exp in previous_expenses)
    
    # Category analysis
    current_by_category = defaultdict(float)
    previous_by_category = defaultdict(float)
    
    for exp in current_expenses:
        current_by_category[exp.category.name] += exp.amount
    
    for exp in previous_expenses:
        previous_by_category[exp.category.name] += exp.amount
    
    recommendations = []
    
    # Recommendation 1: Budget vs Spending
    if current_user.monthly_budget and current_user.monthly_budget > 0:
        budget_used_percent = (current_total / current_user.monthly_budget) * 100
        remaining = current_user.monthly_budget - current_total
        
        if budget_used_percent > 90:
            recommendations.append({
                'type': 'warning',
                'icon': 'warning',
                'color': 'red',
                'title': 'Budget Alert' if current_user.language == 'en' else 'Alertă Buget',
                'description': f'You\'ve used {budget_used_percent:.1f}% of your monthly budget. Only {abs(remaining):.2f} {current_user.currency} remaining.' if current_user.language == 'en' else f'Ai folosit {budget_used_percent:.1f}% din bugetul lunar. Mai rămân doar {abs(remaining):.2f} {current_user.currency}.'
            })
        elif budget_used_percent < 70 and remaining > 0:
            recommendations.append({
                'type': 'success',
                'icon': 'trending_up',
                'color': 'green',
                'title': 'Great Savings Opportunity' if current_user.language == 'en' else 'Oportunitate de Economisire',
                'description': f'You have {remaining:.2f} {current_user.currency} remaining from your budget. Consider saving or investing it.' if current_user.language == 'en' else f'Mai ai {remaining:.2f} {current_user.currency} din buget. Consideră să economisești sau să investești.'
            })
    
    # Recommendation 2: Category spending changes
    for category_name, current_amount in current_by_category.items():
        if category_name in previous_by_category:
            previous_amount = previous_by_category[category_name]
            if previous_amount > 0:
                change_percent = ((current_amount - previous_amount) / previous_amount) * 100
                
                if change_percent > 50:  # 50% increase
                    recommendations.append({
                        'type': 'warning',
                        'icon': 'trending_up',
                        'color': 'yellow',
                        'title': f'{category_name} Spending Up' if current_user.language == 'en' else f'Cheltuieli {category_name} în Creștere',
                        'description': f'Your {category_name} spending increased by {change_percent:.0f}%. Review recent transactions.' if current_user.language == 'en' else f'Cheltuielile pentru {category_name} au crescut cu {change_percent:.0f}%. Revizuiește tranzacțiile recente.'
                    })
                elif change_percent < -30:  # 30% decrease
                    recommendations.append({
                        'type': 'success',
                        'icon': 'trending_down',
                        'color': 'green',
                        'title': f'{category_name} Savings' if current_user.language == 'en' else f'Economii {category_name}',
                        'description': f'Great job! You reduced {category_name} spending by {abs(change_percent):.0f}%.' if current_user.language == 'en' else f'Foarte bine! Ai redus cheltuielile pentru {category_name} cu {abs(change_percent):.0f}%.'
                    })
    
    # Recommendation 3: Unusual transactions
    if current_expenses:
        category_averages = {}
        for category_name, amount in current_by_category.items():
            count = sum(1 for exp in current_expenses if exp.category.name == category_name)
            category_averages[category_name] = amount / count if count > 0 else 0
        
        for exp in current_expenses[-10:]:  # Check last 10 transactions
            category_avg = category_averages.get(exp.category.name, 0)
            if category_avg > 0 and exp.amount > category_avg * 2:  # 200% of average
                recommendations.append({
                    'type': 'info',
                    'icon': 'info',
                    'color': 'blue',
                    'title': 'Unusual Transaction' if current_user.language == 'en' else 'Tranzacție Neobișnuită',
                    'description': f'A transaction of {exp.amount:.2f} {current_user.currency} in {exp.category.name} is higher than usual.' if current_user.language == 'en' else f'O tranzacție de {exp.amount:.2f} {current_user.currency} în {exp.category.name} este mai mare decât de obicei.'
                })
                break  # Only show one unusual transaction warning
    
    # Limit to top 3 recommendations
    recommendations = recommendations[:3]
    
    # If no recommendations, add a positive message
    if not recommendations:
        recommendations.append({
            'type': 'success',
            'icon': 'check_circle',
            'color': 'green',
            'title': 'Spending on Track' if current_user.language == 'en' else 'Cheltuieli sub Control',
            'description': 'Your spending patterns look healthy. Keep up the good work!' if current_user.language == 'en' else 'Obiceiurile tale de cheltuieli arată bine. Continuă așa!'
        })
    
    return jsonify({
        'success': True,
        'recommendations': recommendations
    })
