# 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, perm_required
from .audit import log_action
from core.models import Branch
from inventory.models import Product
from sales.models import POSOrder, POSOrderItem, DailySalesSummary, UnusualTransaction
from django.core.paginator import Paginator


# ─────────────────────────────────────────────────
# AUTH & PASSWORD RESET
# ─────────────────────────────────────────────────

from django.contrib.auth.views import PasswordResetView
from django.contrib.auth.forms import PasswordResetForm

class CompanyAwarePasswordResetForm(PasswordResetForm):
    def get_users(self, email):
        """Scope password resets to the target company if requested through a company URL."""
        users = super().get_users(email)
        company = getattr(self, 'company', None)
        if company:
            return (u for u in users if u.company_id == company.id)
        return users

class CustomPasswordResetView(PasswordResetView):
    form_class = CompanyAwarePasswordResetForm

    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        # Inject the active request company (if any) horizontally into the form
        form.company = getattr(self.request, 'company', None)
        return form

def _is_2fa_required(user):
    """Return True if the company requires 2FA for this user's role."""
    company = getattr(user, 'company', None)
    if not company:
        return False
    # Check plan gate first
    plan = getattr(company, 'plan', None)
    if not plan or not getattr(plan, 'feature_2fa', False):
        return False
    cs = getattr(company, 'settings', None)
    if not cs:
        return False
    if user.role == 'admin' and cs.require_2fa_for_admin:
        return True
    if user.role == 'manager' and cs.require_2fa_for_manager:
        return True
    return False


def _send_2fa_otp(request, user):
    """Generate OTP, store in session, send email. Returns True if email was dispatched."""
    import random, time
    otp_code = f"{random.randint(100000, 999999)}"
    request.session['2fa_otp'] = otp_code
    request.session['2fa_user_pk'] = user.pk
    request.session['2fa_expires'] = time.time() + 600   # 10 minutes
    request.session['2fa_attempts'] = 0
    request.session['2fa_sent_at'] = time.time()

    company = getattr(user, 'company', None)
    company_name = getattr(getattr(company, 'settings', None), 'business_name', None) or (company.name if company else 'SwiftPOS')

    from core.email_utils import send_2fa_otp_email
    send_2fa_otp_email(
        user_email=user.email,
        otp_code=otp_code,
        company_name=company_name,
        username=user.get_full_name() or user.username,
    )
    return True


def login_view(request):
    if request.user.is_authenticated:
        if request.user.is_superuser:
            return redirect('superadmin_company_list')
        company = getattr(request.user, 'company', None)
        if company:
            return redirect(f'/{company.slug}/dashboard/')
        return redirect('company_inactive')

    # Load reCAPTCHA config once for both GET and POST
    from core.models import SiteConfiguration
    _cfg = SiteConfiguration.get_solo()
    recaptcha_enabled  = _cfg.recaptcha_enabled and bool(_cfg.recaptcha_site_key)
    recaptcha_site_key = _cfg.recaptcha_site_key if recaptcha_enabled else ''

    if request.method == 'POST':
        # ── reCAPTCHA gate ───────────────────────────────────────────────
        if recaptcha_enabled:
            from core.recaptcha import verify_recaptcha
            token = request.POST.get('g-recaptcha-response', '')
            if not verify_recaptcha(token, remote_ip=request.META.get('REMOTE_ADDR')):
                messages.error(request, 'Please complete the reCAPTCHA verification.')
                return render(request, 'accounts/login.html', {
                    'form': CustomLoginForm(),
                    'recaptcha_enabled': recaptcha_enabled,
                    'recaptcha_site_key': recaptcha_site_key,
                })
        # ── /reCAPTCHA gate ──────────────────────────────────────────────

        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:
                # ── 2FA Gate ──────────────────────────────────────────────────
                if _is_2fa_required(user):
                    if not user.email:
                        # No email configured — skip 2FA with a warning and let them in
                        messages.warning(request, 'Two-factor authentication is enabled but your account has no email address set. Contact your administrator.')
                        login(request, user)
                        log_action(request, 'login', target=f'User: {user.username}')
                        company = getattr(user, 'company', None)
                        if user.is_superuser:
                            return redirect('superadmin_company_list')
                        if not company:
                            return redirect('company_inactive')
                        slug = company.slug
                        if user.role == 'cashier':
                            cs = getattr(company, 'settings', None)
                            return redirect(f'/{slug}/sales/pos/grid/' if cs and cs.pos_interface_mode == 'grid' else f'/{slug}/sales/pos/')
                        return redirect(f'/{slug}/dashboard/')

                    _send_2fa_otp(request, user)
                    company = getattr(user, 'company', None)
                    company_name = getattr(getattr(company, 'settings', None), 'business_name', None) or (company.name if company else 'SwiftPOS')
                    masked = _mask_email(user.email)
                    request.session['2fa_company_name'] = company_name
                    request.session['2fa_masked_email'] = masked
                    # Redirect with slug prefix so the middleware can resolve the company
                    slug = company.slug if company else None
                    if slug:
                        return redirect(f'/{slug}/accounts/2fa/verify/')
                    return redirect('two_fa_verify')
                # ── /2FA Gate ─────────────────────────────────────────────────

                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.is_superuser:
                    # ── Superadmin 2FA gate ───────────────────────────────────
                    try:
                        from companies.models import SuperAdmin2FA
                        from companies.views import _sa_2fa_send_email_otp
                        sa_2fa = SuperAdmin2FA.objects.get(user=user, is_enabled=True)
                        # Flag the session as pending 2FA
                        request.session['superadmin_2fa_pending'] = True
                        # For email method, send OTP immediately
                        if sa_2fa.method == SuperAdmin2FA.METHOD_EMAIL:
                            if user.email:
                                _sa_2fa_send_email_otp(request, user)
                            else:
                                # No email — warn and let through
                                messages.warning(request, '2FA is enabled but your account has no email. Configure one in Django admin.')
                                request.session.pop('superadmin_2fa_pending', None)
                        return redirect('superadmin_2fa_verify')
                    except SuperAdmin2FA.DoesNotExist:
                        pass  # 2FA not configured or not enabled — proceed normally
                    # ── /Superadmin 2FA gate ──────────────────────────────────
                    return redirect('superadmin_company_list')

                company = getattr(user, 'company', None)
                if not company:
                    return redirect('company_inactive')

                slug = company.slug
                if user.role == 'cashier':
                    company_settings = getattr(company, 'settings', None)
                    pos_mode = getattr(company_settings, 'pos_interface_mode', 'classic') if company_settings else 'classic'
                    if pos_mode == 'grid':
                        return redirect(f'/{slug}/sales/pos/grid/')
                    return redirect(f'/{slug}/sales/pos/')
                else:
                    return redirect(f'/{slug}/dashboard/')
            else:
                messages.error(request, 'Invalid username or password.')
                # ── Log failed login attempt ──────────────────────────────────
                from .audit import log_action as _log
                _log(
                    request, 'login_failed',
                    target=f'Username attempt: {form.cleaned_data.get("username", "unknown")}',
                )
                # ── Increment rate-limit failure counter ──────────────────────
                from core.middleware import _increment_login_failure
                _increment_login_failure(
                    request.META.get('HTTP_X_FORWARDED_FOR', '').split(',')[0].strip()
                    or request.META.get('REMOTE_ADDR', '0.0.0.0')
                )
    else:
        form = CustomLoginForm()
    return render(request, 'accounts/login.html', {
        'form': form,
        'recaptcha_enabled': recaptcha_enabled,
        'recaptcha_site_key': recaptcha_site_key,
    })


def _mask_email(email):
    """Return a masked version: a****@domain.com"""
    try:
        local, domain = email.split('@', 1)
        return local[0] + '*' * min(len(local) - 1, 4) + '@' + domain
    except Exception:
        return '****@****.***'


def two_fa_verify(request):
    """Step 2 of login: verify the OTP sent to the user's email."""
    import time
    from django.contrib.auth import get_user_model

    User = get_user_model()

    # Must have a pending 2FA session
    user_pk = request.session.get('2fa_user_pk')
    if not user_pk:
        messages.error(request, 'Session expired. Please log in again.')
        return redirect('login')

    # Already logged in — shouldn't be here
    if request.user.is_authenticated:
        company = getattr(request.user, 'company', None)
        if company:
            return redirect(f'/{company.slug}/dashboard/')
        return redirect('login')

    masked_email = request.session.get('2fa_masked_email', '****@****.***')
    company_name = request.session.get('2fa_company_name', 'SwiftPOS')

    if request.method == 'POST':
        entered_code = request.POST.get('otp_code', '').strip().replace(' ', '')

        # Attempt limit
        attempts = request.session.get('2fa_attempts', 0)
        if attempts >= 5:
            # Clear session and force re-login
            _clear_2fa_session(request)
            messages.error(request, 'Too many incorrect attempts. Please log in again.')
            return redirect('login')

        # Expiry check
        expires = request.session.get('2fa_expires', 0)
        if time.time() > expires:
            _clear_2fa_session(request)
            messages.error(request, 'Your verification code has expired. Please log in again.')
            return redirect('login')

        stored_otp = request.session.get('2fa_otp', '')

        if entered_code == stored_otp:
            # Success — complete the login
            try:
                user = User.objects.get(pk=user_pk)
            except User.DoesNotExist:
                _clear_2fa_session(request)
                messages.error(request, 'User not found. Please log in again.')
                return redirect('login')

            _clear_2fa_session(request)
            login(request, user)
            log_action(request, 'login', target=f'User: {user.username} (2FA verified)')
            messages.success(request, f'Welcome back, {user.get_full_name() or user.username}!')

            company = getattr(user, 'company', None)
            if user.is_superuser:
                return redirect('superadmin_company_list')
            if not company:
                return redirect('company_inactive')
            slug = company.slug
            if user.role == 'cashier':
                cs = getattr(company, 'settings', None)
                return redirect(f'/{slug}/sales/pos/grid/' if cs and cs.pos_interface_mode == 'grid' else f'/{slug}/sales/pos/')
            return redirect(f'/{slug}/dashboard/')
        else:
            request.session['2fa_attempts'] = attempts + 1
            remaining = 5 - (attempts + 1)
            messages.error(request, f'Incorrect code. {remaining} attempt{"s" if remaining != 1 else ""} remaining.')

    # Calculate seconds since last send for cooldown display
    sent_at = request.session.get('2fa_sent_at', 0)
    seconds_since_send = int(time.time() - sent_at)
    resend_cooldown = max(0, 30 - seconds_since_send)

    return render(request, 'accounts/2fa_verify.html', {
        'masked_email': masked_email,
        'company_name': company_name,
        'resend_cooldown': resend_cooldown,
    })


def two_fa_resend(request):
    """Resend the 2FA OTP to the user's email."""
    import time
    from django.contrib.auth import get_user_model

    User = get_user_model()
    user_pk = request.session.get('2fa_user_pk')
    if not user_pk:
        messages.error(request, 'Session expired. Please log in again.')
        return redirect('login')

    # Enforce 30-second cooldown
    sent_at = request.session.get('2fa_sent_at', 0)
    if time.time() - sent_at < 30:
        messages.warning(request, 'Please wait before requesting a new code.')
        # Preserve the company slug in the redirect
        from django.contrib.auth import get_user_model as _gum
        _User = _gum()
        try:
            _u = _User.objects.get(pk=user_pk)
            _co = getattr(_u, 'company', None)
            if _co and _co.slug:
                return redirect(f'/{_co.slug}/accounts/2fa/verify/')
        except _User.DoesNotExist:
            pass
        return redirect('two_fa_verify')

    try:
        user = User.objects.get(pk=user_pk)
    except User.DoesNotExist:
        _clear_2fa_session(request)
        messages.error(request, 'Session invalid. Please log in again.')
        return redirect('login')

    _send_2fa_otp(request, user)
    messages.success(request, f'A new verification code has been sent to {request.session.get("2fa_masked_email", "your email")}.')
    # Redirect with slug prefix so the middleware resolves the correct company
    _company = getattr(user, 'company', None)
    if _company and _company.slug:
        return redirect(f'/{_company.slug}/accounts/2fa/verify/')
    return redirect('two_fa_verify')


def _clear_2fa_session(request):
    """Remove all 2FA-related session keys."""
    for key in ('2fa_otp', '2fa_user_pk', '2fa_expires', '2fa_attempts', '2fa_sent_at', '2fa_masked_email', '2fa_company_name'):
        request.session.pop(key, None)


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 = None  # SystemSettings removed
    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(company=request.company, 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(company=request.company, 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(company=request.company, 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(company=request.company, 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(company=request.company, 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.filter(company=request.company).count()
    in_stock_products = Product.objects.filter(company=request.company, stock_quantity__gt=0).count()
    low_stock_products = Product.objects.filter(company=request.company, stock_status='low_stock').count()
    out_of_stock_products = Product.objects.filter(company=request.company, stock_status='out_of_stock').count()

    company_qs = CustomUser.objects.filter(company=request.company).exclude(is_superuser=True)
    total_users = company_qs.count()
    active_users = company_qs.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(company=request.company, 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')

    # ── Subscription / Plan data ──
    from companies.models import CompanySettings
    company = getattr(request, 'company', None)
    plan = getattr(company, 'plan', None)
    
    sub_data = None
    days_until_expiry = None
    license_expired = False
    whatsapp_number = None
    license_obj = None

    if plan and company:
        from accounts.models import CustomUser as _CU
        from inventory.models import ProductCategory

        def _pct(current, maximum):
            if maximum and maximum > 0:
                return min(round(current / maximum * 100), 100)
            return None

        # Feature flags to display (label, plan attr)
        feature_flags = [
            ('POS Terminal V1',      plan.feature_pos_terminal_v1),
            ('Smart Grid POS V2',    plan.feature_pos_terminal_v2_grid),
            ('Barcode POS',          plan.feature_barcode_pos),
            ('Bulk Import',          plan.feature_bulk_import),
            ('Data Export',          plan.feature_export),
            ('P&L Reports',          plan.feature_profit_loss),
            ('Audit Logs',           plan.feature_audit_logs),
            ('Multi-Branch',         plan.feature_multi_branch),
            ('Wholesale Pricing',    plan.feature_wholesale_price),
            ('Discounts',            plan.feature_discount),
            ('Promo Codes',          plan.feature_promo),
            ('Credit Sales',         plan.feature_credit_sales),
            ('Advanced Reports',     plan.feature_advanced_reports),
        ]

        # Expiry data
        today_date = timezone.now().date()
        days_until_expiry = None
        license_expired = company.is_expired
        if company.expiry_date:
            days_until_expiry = (company.expiry_date - today_date).days
            if days_until_expiry < 0:
                days_until_expiry = 0
                license_expired = True

        sub_data = {
            'plan_name':          plan.name,
            'plan_price':         plan.price_monthly,
            'is_active':          company.is_active,
            'is_expired':         license_expired,
            'is_accessible':      company.is_accessible,
            'expiry_date':        company.expiry_date,
            'days_until_expiry':  days_until_expiry,
            # Usage
            'products_count':     total_inventory,
            'max_products':       plan.max_products,
            'products_pct':       _pct(total_inventory, plan.max_products),
            'categories_count':   ProductCategory.objects.filter(company=company).count(),
            'max_categories':     plan.max_categories,
            'categories_pct':     _pct(ProductCategory.objects.filter(company=company).count(), plan.max_categories),
            'orders_today':       today_transactions,
            'max_orders_per_day': plan.max_orders_per_day,
            'orders_pct':         _pct(today_transactions, plan.max_orders_per_day),
            'users_count':        total_users,
            'max_staff':          plan.max_staff,
            'users_pct':          _pct(total_users, plan.max_staff),
            'max_branches':       plan.max_branches,
            # Features
            'features':           feature_flags,
        }
        
        # Pull extra context for the banner
        whatsapp_number = company.whatsapp_number
        license_obj = company # For backward compatibility in template

    # ── 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(company=request.company, 
            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
        'sub_data': sub_data,
        '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
@perm_required('can_manage_users')
def user_management(request):
    """Company-scoped user management. Superadmins are never shown to company admins."""
    company = request.company
    users = CustomUser.objects.filter(company=company).exclude(is_superuser=True).order_by('username')

    current_users = users.filter(is_active=True).count()
    plan = getattr(company, 'plan', None) if company else None
    max_users = int(getattr(plan, 'max_staff', 0) or 0) if plan else 0

    can_add_user = True
    user_limit_message = ''

    if max_users > 0 and current_users >= max_users:
        can_add_user = False
        user_limit_message = f'You have reached your staff limit ({max_users} users on your plan).'

    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
@perm_required('can_manage_users')
def user_create(request):
    if request.method == 'POST':
        form = UserCreateForm(request.POST, company=request.company)
        if form.is_valid():
            user = form.save(commit=False)
            user.company = request.company  # always assign to current company
            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(company=request.company)
    return render(request, 'accounts/user_form.html', {'form': form, 'mode': 'create'})


@login_required
@perm_required('can_manage_users')
def user_edit(request, pk):
    user_obj = get_object_or_404(CustomUser, pk=pk, company=request.company)
    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, company=request.company)
        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, company=request.company)
    return render(request, 'accounts/user_form.html', {'form': form, 'mode': 'edit', 'user_obj': user_obj})


@login_required
@perm_required('can_manage_users')
def user_list(request):
    """List company-scoped staff only. Superusers/superadmins never shown."""
    users = (
        CustomUser.objects
        .filter(company=request.company)
        .exclude(is_superuser=True)
        .select_related('branch')
        .order_by('date_joined')
    )
    return render(request, 'accounts/user_list.html', {'users': users})


@login_required
@perm_required('can_manage_users')
def delete_user(request, user_id):
    if request.method == 'POST':
        user = get_object_or_404(CustomUser, id=user_id, company=request.company)
        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
@perm_required('can_view_audit_log')
def audit_log(request):
    """Display filterable audit log for admin. Gated by plan.feature_audit_logs."""
    # ── Subscription gate via plan feature flag OR company override ──
    if not request.user.is_superuser:
        company = getattr(request, 'company', None)
        plan = getattr(company, 'plan', None)
        company_settings = getattr(company, 'settings', None)
        plan_allows = plan and getattr(plan, 'feature_audit_logs', False)
        settings_override = company_settings and getattr(company_settings, 'enable_audit_log', False)
        if not plan_allows and not settings_override:
            from django.urls import reverse
            return redirect(reverse('upgrade_required') + '?feature=Audit+Log&required_plan=Standard')
    # ── /Subscription gate ────────────────────────────────────────────

    logs_qs = AuditLog.objects.select_related('user').filter(company=request.company)



    # Hide superadmin actions from standard tenant admins

    if not request.user.is_superuser and request.user.role != 'superadmin':

        from django.db.models import Q

        logs_qs = logs_qs.exclude(Q(user__is_superuser=True) | Q(user__role='superadmin'))

    # Hide superadmin actions from standard tenant admins
    if not request.user.is_superuser and request.user.role != 'superadmin':
        from django.db.models import Q
        logs_qs = logs_qs.exclude(Q(user__is_superuser=True) | Q(user__role='superadmin'))

    # 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.filter(company=request.company).exclude(is_superuser=True).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(),
    })

