# accounts/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse
from django.utils import timezone
from django.db.models import Sum, Count, Avg, F, Q
from datetime import datetime, timedelta
from .forms import CustomLoginForm, UserCreateForm, UserUpdateForm
from .models import CustomUser, AuditLog
from .decorators import role_required
from .audit import log_action
from core.models import SystemSettings, SubscriptionPlan, License, Branch
from inventory.models import Product
from sales.models import POSOrder, POSOrderItem, DailySalesSummary, UnusualTransaction
from django.core.paginator import Paginator


# ─────────────────────────────────────────────────
# AUTH
# ─────────────────────────────────────────────────

def login_view(request):
    if request.user.is_authenticated:
        return redirect('dashboard')
    if request.method == 'POST':
        form = CustomLoginForm(request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                log_action(request, 'login', target=f'User: {user.username}')
                messages.success(request, f'Welcome back, {user.get_full_name() or user.username}!')
                if user.role == 'cashier':
                    return redirect('sales:pos')
                else:
                    return redirect('dashboard')
            else:
                messages.error(request, 'Invalid username or password.')
    else:
        form = CustomLoginForm()
    return render(request, 'accounts/login.html', {'form': form})


def logout_view(request):
    log_action(request, 'logout', target=f'User: {request.user.username}')
    logout(request)
    messages.info(request, 'You have been logged out successfully.')
    return redirect('login')


# ─────────────────────────────────────────────────
# PIN VERIFICATION (AJAX)
# ─────────────────────────────────────────────────

@login_required
def verify_pin(request):
    """AJAX endpoint: POST {pin, action} → {ok, message}"""
    if request.method != 'POST':
        return JsonResponse({'ok': False, 'message': 'Method not allowed'}, status=405)
    try:
        import json
        data = json.loads(request.body)
        raw_pin = str(data.get('pin', '')).strip()
        action_label = data.get('action', 'protected action')
    except Exception:
        raw_pin = request.POST.get('pin', '').strip()
        action_label = request.POST.get('action', 'protected action')

    user = request.user
    if not user.pin_hash:
        return JsonResponse({'ok': False, 'message': 'No PIN set for your account. Ask admin to set one.'})

    if user.check_pin(raw_pin):
        log_action(request, 'pin_verified', target=action_label)
        return JsonResponse({'ok': True, 'message': 'PIN accepted'})
    else:
        return JsonResponse({'ok': False, 'message': 'Incorrect PIN. Try again.'})


# ─────────────────────────────────────────────────
# DASHBOARD
# ─────────────────────────────────────────────────

@login_required
def dashboard(request):
    user = request.user
    today = timezone.now().date()

    system_settings = SystemSettings.objects.first()
    plan = None
    allow_multi_branch_plan = False
    license_obj = None
    days_until_expiry = None
    license_expired = False
    whatsapp_number = ''

    if system_settings:
        try:
            license_obj = system_settings.license
            plan = license_obj.plan
            allow_multi_branch_plan = bool(getattr(plan, 'allow_multi_branch', False))
            if license_obj.expires_at:
                delta = (license_obj.expires_at - today).days
                days_until_expiry = delta
                if delta < 0:
                    license_expired = True
        except License.DoesNotExist:
            allow_multi_branch_plan = False

    try:
        from django.conf import settings as djsettings
        whatsapp_number = getattr(djsettings, 'WHATSAPP_NUMBER', '')
    except Exception:
        pass

    branches = Branch.objects.filter(is_active=True).order_by('name')
    selected_branch = None

    if user.role in ('manager', 'cashier'):
        selected_branch = getattr(user, 'branch', None)
        allow_multi_branch = False
    else:
        allow_multi_branch = allow_multi_branch_plan
        branch_id = request.GET.get('branch') or ''
        if branch_id:
            try:
                selected_branch = branches.get(id=branch_id)
            except Branch.DoesNotExist:
                selected_branch = None

    def filter_orders(qs):
        if selected_branch:
            return qs.filter(branch=selected_branch)
        if user.role in ('manager', 'cashier') and getattr(user, 'branch', None):
            return qs.filter(branch=user.branch)
        return qs

    yesterday_date = today - timedelta(days=1)
    week_start = today - timedelta(days=6)
    month_start = today.replace(day=1)
    month_back_30 = today - timedelta(days=30)

    today_orders = filter_orders(POSOrder.objects.filter(created_at__date=today, status='completed'))
    today_sales = today_orders.aggregate(total=Sum('final_amount'))['total'] or 0
    today_transactions = today_orders.count()
    today_customers = (today_orders.exclude(customer_name='').values('customer_name', 'customer_phone').distinct().count())
    avg_order_value = (today_sales / today_transactions) if today_transactions else 0

    yesterday_orders = filter_orders(POSOrder.objects.filter(created_at__date=yesterday_date, status='completed'))
    yesterday_sales = yesterday_orders.aggregate(total=Sum('final_amount'))['total'] or 0
    yesterday_transactions = yesterday_orders.count()

    weekly_orders = filter_orders(POSOrder.objects.filter(created_at__date__gte=week_start, created_at__date__lte=today, status='completed'))
    weekly_sales = weekly_orders.aggregate(total=Sum('final_amount'))['total'] or 0
    weekly_transactions = weekly_orders.count()

    monthly_orders = filter_orders(POSOrder.objects.filter(created_at__date__gte=month_start, created_at__date__lte=today, status='completed'))
    monthly_sales = monthly_orders.aggregate(total=Sum('final_amount'))['total'] or 0
    monthly_transactions = monthly_orders.count()

    if yesterday_sales and float(yesterday_sales) > 0:
        sales_growth_percentage = ((float(today_sales) - float(yesterday_sales)) / float(yesterday_sales)) * 100.0
    else:
        sales_growth_percentage = 0

    total_inventory = Product.objects.count()
    in_stock_products = Product.objects.filter(stock_quantity__gt=0).count()
    low_stock_products = Product.objects.filter(stock_status='low_stock').count()
    out_of_stock_products = Product.objects.filter(stock_status='out_of_stock').count()

    total_users = CustomUser.objects.exclude(role='superadmin').count()
    active_users = CustomUser.objects.exclude(role='superadmin').filter(is_active=True).count()

    payment_breakdown = []
    method_labels = dict(POSOrder.PAYMENT_METHODS)
    payment_rows = today_orders.values('payment_method').annotate(total=Sum('final_amount'), count=Count('id')).order_by('-total')
    total_today_amount = sum(row['total'] or 0 for row in payment_rows)
    for row in payment_rows:
        code = row['payment_method']
        total = row['total'] or 0
        pct = float(total) / float(total_today_amount) * 100.0 if total_today_amount else 0.0
        payment_breakdown.append({'code': code, 'label': method_labels.get(code, code), 'total': total, 'count': row['count'], 'percentage': round(pct, 1)})

    recent_orders = today_orders.order_by('-created_at')[:5]
    items_today = POSOrderItem.objects.filter(order__in=today_orders)
    top_selling_items = items_today.values('product__name', 'product__sku').annotate(total_quantity=Sum('quantity'), total_revenue=Sum('total_price')).order_by('-total_quantity')[:5]
    last_30_orders = filter_orders(POSOrder.objects.filter(created_at__date__gte=month_back_30, created_at__date__lte=today, status='completed'))
    best_customers = last_30_orders.exclude(customer_name='').values('customer_name').annotate(total_spent=Sum('final_amount'), orders=Count('id')).order_by('-total_spent')[:5]
    cashier_performance = today_orders.values('cashier').annotate(total_orders=Count('id'), total_sales=Sum('final_amount')).order_by('-total_sales')

    # ── Weekly chart data (last 7 days) ──
    import json
    weekly_labels = []
    weekly_revenue_data = []
    weekly_orders_data = []
    for i in range(6, -1, -1):
        day = today - timedelta(days=i)
        day_orders = filter_orders(POSOrder.objects.filter(
            created_at__date=day,
            status='completed'
        ))
        rev = day_orders.aggregate(total=Sum('final_amount'))['total'] or 0
        cnt = day_orders.count()
        weekly_labels.append(day.strftime('%a'))
        weekly_revenue_data.append(float(rev))
        weekly_orders_data.append(cnt)

    context = {
        'user_role': user.role,
        'user_name': user.get_full_name() or user.username,
        'allow_multi_branch': allow_multi_branch,
        'branches': branches,
        'selected_branch': selected_branch,
        'today_sales': today_sales,
        'today_transactions': today_transactions,
        'today_customers': today_customers,
        'avg_order_value': avg_order_value,
        'total_inventory': total_inventory,
        'in_stock_products': in_stock_products,
        'low_stock_products': low_stock_products,
        'out_of_stock_products': out_of_stock_products,
        'total_users': total_users,
        'active_users': active_users,
        'yesterday_sales': yesterday_sales,
        'yesterday_transactions': yesterday_transactions,
        'weekly_sales': weekly_sales,
        'weekly_transactions': weekly_transactions,
        'monthly_sales': monthly_sales,
        'monthly_transactions': monthly_transactions,
        'sales_growth_percentage': sales_growth_percentage,
        'payment_breakdown': payment_breakdown,
        'recent_orders': recent_orders,
        'top_selling_items': top_selling_items,
        'best_customers': best_customers,
        'cashier_performance': cashier_performance,
        'weekly_labels': json.dumps(weekly_labels),
        'weekly_revenue_data': json.dumps(weekly_revenue_data),
        'weekly_orders_data': json.dumps(weekly_orders_data),
        # subscription renewal
        'license_obj': license_obj,
        'days_until_expiry': days_until_expiry,
        'license_expired': license_expired,
        'whatsapp_number': whatsapp_number,
    }
    return render(request, 'accounts/dashboard.html', context)


# ─────────────────────────────────────────────────
# USER MANAGEMENT
# ─────────────────────────────────────────────────

@login_required
@role_required(['admin'])
def user_management(request):
    users = CustomUser.objects.exclude(role='superadmin').order_by('username')
    system_settings = SystemSettings.objects.first()
    can_add_user = True
    user_limit_message = ''
    max_users = 0
    current_users = CustomUser.objects.filter(is_active=True).exclude(is_superuser=True).count()

    if not system_settings:
        can_add_user = False
        user_limit_message = 'System settings not found. Contact support.'
    else:
        try:
            license_obj = system_settings.license
        except License.DoesNotExist:
            can_add_user = False
            user_limit_message = 'No active license found. You cannot add users.'
        else:
            if not license_obj.is_active:
                can_add_user = False
                user_limit_message = 'Your license is inactive. You cannot add users.'
            elif license_obj.is_expired:
                can_add_user = False
                user_limit_message = 'Your license has expired. You cannot add users.'
            else:
                plan = license_obj.plan
                max_users = getattr(plan, 'max_users', 0) or 0
                if max_users > 0 and current_users >= max_users:
                    can_add_user = False
                    user_limit_message = f'You have reached your user limit ({max_users} users).'

    return render(request, 'accounts/user_management.html', {
        'users': users,
        'can_add_user': can_add_user,
        'user_limit_message': user_limit_message,
        'current_users_count': current_users,
        'max_users': max_users,
        'user_role': request.user.role,
        'user_name': request.user.get_full_name() or request.user.username,
    })


@login_required
@role_required(['admin'])
def user_create(request):
    if request.method == 'POST':
        form = UserCreateForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            raw_pin = request.POST.get('pin_raw', '').strip()
            if raw_pin:
                user.set_pin(raw_pin)
            user.save()
            log_action(request, 'create_user', target=f'User: {user.username}')
            messages.success(request, 'User created successfully.')
            return redirect('user_list')
    else:
        form = UserCreateForm()
    return render(request, 'accounts/user_form.html', {'form': form, 'mode': 'create'})


@login_required
@role_required(['admin'])
def user_edit(request, pk):
    user_obj = get_object_or_404(CustomUser, pk=pk)
    if user_obj.role == 'superadmin':
        messages.error(request, 'Superadmin cannot be edited from this page.')
        return redirect('user_list')

    if request.method == 'POST':
        form = UserUpdateForm(request.POST, instance=user_obj)
        if form.is_valid():
            updated_user = form.save(commit=False)
            raw_pin = request.POST.get('pin_raw', '').strip()
            if raw_pin:
                updated_user.set_pin(raw_pin)
                log_action(request, 'set_pin', target=f'User: {updated_user.username}')
            updated_user.save()
            log_action(request, 'edit_user', target=f'User: {updated_user.username}')
            messages.success(request, 'User updated successfully.')
            return redirect('user_list')
    else:
        form = UserUpdateForm(instance=user_obj)
    return render(request, 'accounts/user_form.html', {'form': form, 'mode': 'edit', 'user_obj': user_obj})


@login_required
@role_required(['admin'])
def user_list(request):
    users = CustomUser.objects.exclude(role='superadmin').select_related('branch').order_by('date_joined')
    return render(request, 'accounts/user_list.html', {'users': users})


@login_required
@role_required(['admin'])
def delete_user(request, user_id):
    if request.method == 'POST':
        user = get_object_or_404(CustomUser, id=user_id)
        if user.role == 'superadmin':
            messages.error(request, 'You cannot delete a superadmin account.')
            return redirect('user_management')
        username = user.username
        user.delete()
        log_action(request, 'delete_user', target=f'User: {username}')
        messages.success(request, f'User {username} deleted successfully!')
        return redirect('user_management')
    return redirect('user_management')


# ─────────────────────────────────────────────────
# AUDIT LOG
# ─────────────────────────────────────────────────

@login_required
@role_required(['admin', 'superadmin'])
def audit_log(request):
    """Display filterable audit log for admin. Gated by plan.allow_audit_log."""
    # ── Subscription gate ─────────────────────────────
    try:
        from core.utils import get_current_license
        lic = get_current_license()
        plan = getattr(lic, 'plan', None)
        if plan and not getattr(plan, 'allow_audit_log', False):
            from django.urls import reverse
            return redirect(reverse('upgrade_required') + '?feature=Audit+Log&required_plan=Standard')
    except Exception:
        pass
    # ── /Subscription gate ────────────────────────────
    logs_qs = AuditLog.objects.select_related('user').all()

    # Filters
    date_from = request.GET.get('date_from', '')
    date_to = request.GET.get('date_to', '')
    action_filter = request.GET.get('action', '')
    user_filter = request.GET.get('user_id', '')

    if date_from:
        try:
            logs_qs = logs_qs.filter(timestamp__date__gte=datetime.strptime(date_from, '%Y-%m-%d').date())
        except ValueError:
            pass
    if date_to:
        try:
            logs_qs = logs_qs.filter(timestamp__date__lte=datetime.strptime(date_to, '%Y-%m-%d').date())
        except ValueError:
            pass
    if action_filter:
        logs_qs = logs_qs.filter(action=action_filter)
    if user_filter:
        logs_qs = logs_qs.filter(user_id=user_filter)

    paginator = Paginator(logs_qs, 25)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    users_list = CustomUser.objects.exclude(role='superadmin').order_by('username')
    action_choices = AuditLog.ACTION_CHOICES

    return render(request, 'accounts/audit_log.html', {
        'page_obj': page_obj,
        'users_list': users_list,
        'action_choices': action_choices,
        'date_from': date_from,
        'date_to': date_to,
        'action_filter': action_filter,
        'user_filter': user_filter,
        'user_role': request.user.role,
        'user_name': request.user.get_full_name() or request.user.username,
        'total_count': logs_qs.count(),
    })
