# companies/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponseForbidden

from .models import Company, CompanySettings, Plan, SuperAdmin2FA


def company_inactive(request):
    """Shown when a company's subscription has expired or is suspended."""
    company = getattr(request, 'company', None)
    return render(request, 'companies/inactive.html', {'company': company})


# ─────────────────────────────────────────────────────────────
# SUPERADMIN — company management views
# ─────────────────────────────────────────────────────────────

def superadmin_required(view_func):
    """Decorator: only Django superusers can access.
    Also enforces 2FA if enabled for the superuser — redirects to verify page
    until the second factor is confirmed for this session.
    """
    from functools import wraps
    @wraps(view_func)
    def wrapper(request, *args, **kwargs):
        if not request.user.is_authenticated or not request.user.is_superuser:
            return HttpResponseForbidden('Superadmin access only.')
        # If 2FA is pending for this session, bounce to verify page
        if request.session.get('superadmin_2fa_pending'):
            return redirect('superadmin_2fa_verify')
        return view_func(request, *args, **kwargs)
    return wrapper


@superadmin_required
def company_list(request):
    """Superadmin: list all companies + platform-wide revenue overview."""
    from sales.models import POSOrder
    from django.db.models import Sum, Count
    from django.db.models.functions import TruncDate
    from django.utils import timezone
    from decimal import Decimal

    companies = Company.objects.select_related('plan').order_by('name')

    today = timezone.now().date()

    # ── Platform-wide totals ──────────────────────────────────────────────
    completed_orders = POSOrder.objects.filter(status='completed')
    platform_total_revenue = completed_orders.aggregate(t=Sum('final_amount'))['t'] or Decimal('0')
    platform_today_revenue = completed_orders.filter(created_at__date=today).aggregate(t=Sum('final_amount'))['t'] or Decimal('0')
    platform_total_orders  = completed_orders.count()
    platform_today_orders  = completed_orders.filter(created_at__date=today).count()
    active_companies = companies.filter(is_active=True).count()

    # ── Daily revenue last 30 days (sorted by date) ───────────────────────
    from datetime import timedelta
    thirty_days_ago = today - timedelta(days=29)
    daily_revenue = (
        completed_orders
        .filter(created_at__date__gte=thirty_days_ago)
        .annotate(day=TruncDate('created_at'))
        .values('day')
        .annotate(total=Sum('final_amount'), orders=Count('id'))
        .order_by('day')
    )

    # ── Per-company revenue (top companies by revenue) ────────────────────
    company_revenues = (
        completed_orders
        .values('company__name', 'company__slug')
        .annotate(total=Sum('final_amount'), orders=Count('id'))
        .order_by('-total')[:15]
    )

    return render(request, 'companies/superadmin/list.html', {
        'companies': companies,
        'platform_total_revenue': platform_total_revenue,
        'platform_today_revenue': platform_today_revenue,
        'platform_total_orders':  platform_total_orders,
        'platform_today_orders':  platform_today_orders,
        'active_companies': active_companies,
        'daily_revenue': list(daily_revenue),
        'company_revenues': list(company_revenues),
        'today': today,
    })


@superadmin_required
def company_detail(request, slug):
    """Superadmin: view/edit a specific company."""
    from sales.models import POSOrder
    from django.db.models import Sum
    from django.utils import timezone

    company = get_object_or_404(Company, slug=slug)
    cs = getattr(company, 'settings', None)
    
    today = timezone.now().date()
    
    # Calculate stats
    today_sales = POSOrder.objects.filter(company=company, created_at__date=today, status='completed').aggregate(total=Sum('final_amount'))['total'] or 0
    total_revenue = POSOrder.objects.filter(company=company, status='completed').aggregate(total=Sum('final_amount'))['total'] or 0
    today_orders = POSOrder.objects.filter(company=company, created_at__date=today, status='completed').count()
    total_orders_count = POSOrder.objects.filter(company=company, status='completed').count()

    return render(request, 'companies/superadmin/detail.html', {
        'company': company,
        'cs': cs,
        'plans': Plan.objects.filter(is_active=True),
        'today_sales': today_sales,
        'total_revenue': total_revenue,
        'today_orders': today_orders,
        'total_orders_count': total_orders_count,
    })


@superadmin_required
def company_toggle(request, slug):
    """Superadmin: activate/deactivate a company."""
    company = get_object_or_404(Company, slug=slug)
    company.is_active = not company.is_active
    company.save()
    status = "activated" if company.is_active else "suspended"
    messages.success(request, f"Company '{company.name}' has been {status}.")
    return redirect('superadmin_company_list')


@superadmin_required
def company_create(request):
    """Superadmin: create a new company + admin account + branch."""
    plans = Plan.objects.filter(is_active=True)
    if request.method == 'POST':
        from django.utils.text import slugify
        from django.db import transaction
        from accounts.models import CustomUser
        from core.models import Branch

        name = request.POST.get('name', '').strip()
        email = request.POST.get('email', '').strip()
        phone = request.POST.get('phone', '').strip()
        plan_id = request.POST.get('plan')
        expiry_date = request.POST.get('expiry_date')
        
        # Admin user details
        admin_username = request.POST.get('admin_username', '').strip()
        admin_email = request.POST.get('admin_email', '').strip()
        admin_password = request.POST.get('admin_password', '').strip()

        slug = slugify(name)
        if not slug:
            messages.error(request, "Name cannot be empty.")
            return render(request, 'companies/superadmin/create.html', {'plans': plans})

        if Company.objects.filter(slug=slug).exists():
            messages.error(request, f"A company with slug '{slug}' already exists.")
            return render(request, 'companies/superadmin/create.html', {'plans': plans})

        if CustomUser.objects.filter(username=admin_username).exists():
            messages.error(request, f"Username '{admin_username}' is already taken.")
            return render(request, 'companies/superadmin/create.html', {'plans': plans})

        try:
            with transaction.atomic():
                plan = get_object_or_404(Plan, id=plan_id) if plan_id else None
                company = Company.objects.create(
                    name=name, slug=slug, email=email, phone=phone, plan=plan, 
                    is_active=True, expiry_date=expiry_date if expiry_date else None
                )
                CompanySettings.objects.create(company=company, business_name=name)
                
                # Create default branch
                branch = Branch.objects.create(
                    company=company,
                    name="Main Branch",
                    code="MAIN"
                )
                
                # Create admin user
                user = CustomUser.objects.create_user(
                    username=admin_username,
                    email=admin_email,
                    password=admin_password,
                    role='admin',
                    company=company,
                    branch=branch
                )
                
            messages.success(request, f"Company '{name}' and admin user '{admin_username}' created successfully!")
            return redirect('superadmin_company_list')
        except Exception as e:
            messages.error(request, f"Error creating company: {str(e)}")
            return render(request, 'companies/superadmin/create.html', {'plans': plans})

    return render(request, 'companies/superadmin/create.html', {'plans': plans})


@superadmin_required
def company_update_subscription(request, slug):
    """Superadmin: update company plan and expiry date."""
    from subscriptions.models import Subscription, PaymentTransaction
    from django.utils import timezone
    from decimal import Decimal

    company = get_object_or_404(Company, slug=slug)
    if request.method == 'POST':
        plan_id = request.POST.get('plan')
        expiry_date = request.POST.get('expiry_date')
        
        company.plan_id = plan_id if plan_id else None
        company.expiry_date = expiry_date if expiry_date else None
        company.save()
        
        if plan_id:
            # 1. Deactivate all existing active subscriptions
            Subscription.objects.filter(company=company, is_active=True).update(is_active=False)
            
            # 2. Create the new active subscription
            plan = get_object_or_404(Plan, id=plan_id)
            sub = Subscription.objects.create(
                company=company,
                plan=plan,
                billing_cycle='monthly',
                start_date=timezone.now().date(),
                expiry_date=expiry_date if expiry_date else None,
                is_trial=False,
                is_active=True,
                payment_status='paid'
            )
            
            # 3. Create a manual transaction record for billing history
            PaymentTransaction.objects.create(
                company=company,
                subscription=sub,
                plan=plan,
                billing_cycle='monthly',
                amount=Decimal('0.00'),
                discount_amount=Decimal('0.00'),
                final_amount=Decimal('0.00'),
                status='paid',
                payment_method='Manual Override by Admin',
                paid_at=timezone.now()
            )
        
        messages.success(request, f"Subscription for '{company.name}' updated seamlessly.")
        return redirect('superadmin_company_detail', slug=slug)
    return redirect('superadmin_company_detail', slug=slug)


@superadmin_required
def server_setup(request):
    """Superadmin: Integrations & Automation setup guide (webhooks + cPanel cron)."""
    import sys, os
    python_path = sys.executable
    manage_py   = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'manage.py')
    cpanel_cron_command   = f'{python_path} {manage_py} process_subscriptions'
    insights_cron_command = f'{python_path} {manage_py} generate_insights'

    # Build webhook URLs from request
    monnify_webhook_url  = request.build_absolute_uri('/webhooks/monnify/')
    paystack_webhook_url = request.build_absolute_uri('/subscription/webhooks/paystack/')

    return render(request, 'companies/superadmin/server_setup.html', {
        'webhook_url': monnify_webhook_url,           # kept for backward compat
        'monnify_webhook_url': monnify_webhook_url,
        'paystack_webhook_url': paystack_webhook_url,
        'cpanel_cron_command': cpanel_cron_command,
        'insights_cron_command': insights_cron_command,
    })


# ─────────────────────────────────────────────────────────────
# SUPERADMIN 2FA — verification views
# ─────────────────────────────────────────────────────────────

def _sa_2fa_send_email_otp(request, user):
    """Generate OTP, store in session, send email."""
    import random, time
    from core.email_utils import send_2fa_otp_email

    otp = f"{random.randint(100000, 999999)}"
    request.session['sa_2fa_otp']      = otp
    request.session['sa_2fa_expires']  = time.time() + 600   # 10 min
    request.session['sa_2fa_attempts'] = 0
    send_2fa_otp_email(
        user_email=user.email,
        otp_code=otp,
        company_name='SwiftPOS Superadmin',
        username=user.get_full_name() or user.username,
    )


def superadmin_2fa_verify(request):
    """
    Second-factor verification for superusers.
    Supports both email OTP and TOTP (Google Authenticator).
    Only reachable when session['superadmin_2fa_pending'] is True.
    """
    import time

    # Must be logged in as superuser and have a pending 2FA flag
    if not request.user.is_authenticated or not request.user.is_superuser:
        return redirect('login')
    if not request.session.get('superadmin_2fa_pending'):
        return redirect('superadmin_company_list')

    try:
        cfg = SuperAdmin2FA.objects.get(user=request.user, is_enabled=True)
    except SuperAdmin2FA.DoesNotExist:
        # Config deleted while logged in — grant access
        request.session.pop('superadmin_2fa_pending', None)
        return redirect('superadmin_company_list')

    method = cfg.method

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

        if method == SuperAdmin2FA.METHOD_EMAIL:
            # ── Email OTP check ───────────────────────────────────────────
            attempts = request.session.get('sa_2fa_attempts', 0)
            expires  = request.session.get('sa_2fa_expires', 0)
            stored   = request.session.get('sa_2fa_otp', '')

            if time.time() > expires:
                messages.error(request, 'Your OTP has expired. Please request a new one.')
                return redirect('superadmin_2fa_resend')

            if attempts >= 5:
                messages.error(request, 'Too many incorrect attempts. Please log in again.')
                from django.contrib.auth import logout
                logout(request)
                return redirect('login')

            if code == stored:
                request.session.pop('superadmin_2fa_pending', None)
                request.session.pop('sa_2fa_otp', None)
                request.session.pop('sa_2fa_expires', None)
                request.session.pop('sa_2fa_attempts', None)
                messages.success(request, 'Two-factor authentication verified. Welcome!')
                return redirect('superadmin_company_list')
            else:
                request.session['sa_2fa_attempts'] = attempts + 1
                remaining = 5 - (attempts + 1)
                messages.error(request, f'Incorrect code. {remaining} attempt(s) remaining.')

        elif method == SuperAdmin2FA.METHOD_TOTP:
            # ── TOTP check ────────────────────────────────────────────────
            if cfg.verify_totp(code):
                request.session.pop('superadmin_2fa_pending', None)
                messages.success(request, 'Two-factor authentication verified. Welcome!')
                return redirect('superadmin_company_list')
            else:
                messages.error(request, 'Invalid authenticator code. Please try again.')

    return render(request, 'companies/superadmin/2fa_verify.html', {
        'method': method,
        'is_email': method == SuperAdmin2FA.METHOD_EMAIL,
        'is_totp':  method == SuperAdmin2FA.METHOD_TOTP,
        'masked_email': _mask_email(request.user.email) if request.user.email else '',
    })


def superadmin_2fa_resend(request):
    """Resend email OTP for superadmin (email method only)."""
    if not request.user.is_authenticated or not request.user.is_superuser:
        return redirect('login')
    if not request.session.get('superadmin_2fa_pending'):
        return redirect('superadmin_company_list')

    try:
        cfg = SuperAdmin2FA.objects.get(user=request.user, is_enabled=True, method=SuperAdmin2FA.METHOD_EMAIL)
    except SuperAdmin2FA.DoesNotExist:
        return redirect('superadmin_2fa_verify')

    _sa_2fa_send_email_otp(request, request.user)
    messages.success(request, 'A new OTP has been sent to your email.')
    return redirect('superadmin_2fa_verify')


def _mask_email(email):
    if not email or '@' not in email:
        return email
    local, domain = email.split('@', 1)
    return local[:2] + '***@' + domain
