from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse
from django.core.paginator import Paginator
from django.db.models import Q, Sum, Count
from django.utils import timezone
from django.views.decorators.http import require_http_methods
from django.db import transaction

from apps.campaigns.models import Campaign, Brand, Agency, Creative, AdSpot, CampaignReport
from apps.core.models import ActivityLog


@login_required
def campaign_list(request):
    """List all campaigns with filtering and pagination."""
    campaigns = Campaign.objects.select_related('brand', 'agency', 'created_by').all()
    
    # Filtering
    search = request.GET.get('search')
    if search:
        campaigns = campaigns.filter(
            Q(name__icontains=search) |
            Q(brand__name__icontains=search) |
            Q(description__icontains=search)
        )
    
    status = request.GET.get('status')
    if status:
        campaigns = campaigns.filter(status=status)
    
    brand_id = request.GET.get('brand')
    if brand_id:
        campaigns = campaigns.filter(brand_id=brand_id)
    
    # Pagination
    paginator = Paginator(campaigns, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    # Get filter options
    brands = Brand.objects.filter(is_active=True).order_by('name')
    status_choices = Campaign.STATUS_CHOICES
    
    context = {
        'page_obj': page_obj,
        'brands': brands,
        'status_choices': status_choices,
        'current_search': search,
        'current_status': status,
        'current_brand': brand_id,
    }
    
    return render(request, 'campaigns/campaign_list.html', context)


@login_required
def campaign_detail(request, campaign_id):
    """Campaign detail view with performance metrics."""
    campaign = get_object_or_404(
        Campaign.objects.select_related('brand', 'agency', 'created_by', 'approved_by'),
        id=campaign_id
    )
    
    # Get ad spots
    adspots = campaign.adspots.select_related('creative').order_by('position')
    
    # Calculate metrics
    total_impressions = adspots.aggregate(Sum('impressions'))['impressions__sum'] or 0
    total_clicks = adspots.aggregate(Sum('clicks'))['clicks__sum'] or 0
    
    ctr = (total_clicks / total_impressions * 100) if total_impressions > 0 else 0
    
    # Recent activity
    recent_activity = ActivityLog.objects.filter(
        content_type__model='campaign',
        object_id=campaign.id
    ).select_related('user').order_by('-created_at')[:10]
    
    context = {
        'campaign': campaign,
        'adspots': adspots,
        'total_impressions': total_impressions,
        'total_clicks': total_clicks,
        'ctr': round(ctr, 2),
        'recent_activity': recent_activity,
    }
    
    return render(request, 'campaigns/campaign_detail.html', context)


@login_required
def campaign_create(request):
    """Create a new campaign."""
    if request.method == 'POST':
        try:
            with transaction.atomic():
                campaign = Campaign.objects.create(
                    name=request.POST['name'],
                    description=request.POST.get('description', ''),
                    brand_id=request.POST['brand'],
                    agency_id=request.POST.get('agency') or None,
                    campaign_type=request.POST.get('campaign_type', 'standard'),
                    start_date=request.POST['start_date'],
                    end_date=request.POST['end_date'],
                    budget=request.POST.get('budget') or None,
                    target_impressions=request.POST.get('target_impressions') or None,
                    created_by=request.user
                )
                
                # Log activity
                ActivityLog.objects.create(
                    user=request.user,
                    action='CREATE',
                    content_type='Campaign',
                    object_id=campaign.id,
                    description=f'Created campaign: {campaign.name}'
                )
                
                messages.success(request, f'Campaign "{campaign.name}" created successfully.')
                return redirect('campaigns:detail', campaign_id=campaign.id)
                
        except Exception as e:
            messages.error(request, f'Error creating campaign: {str(e)}')
    
    # Get form data
    brands = Brand.objects.filter(is_active=True).order_by('name')
    agencies = Agency.objects.filter(is_active=True).order_by('name')
    
    context = {
        'brands': brands,
        'agencies': agencies,
        'campaign_types': Campaign.CAMPAIGN_TYPES,
    }
    
    return render(request, 'campaigns/campaign_form.html', context)


@login_required
def campaign_edit(request, campaign_id):
    """Edit an existing campaign."""
    campaign = get_object_or_404(Campaign, id=campaign_id)
    
    if request.method == 'POST':
        try:
            with transaction.atomic():
                campaign.name = request.POST['name']
                campaign.description = request.POST.get('description', '')
                campaign.brand_id = request.POST['brand']
                campaign.agency_id = request.POST.get('agency') or None
                campaign.campaign_type = request.POST.get('campaign_type', 'standard')
                campaign.start_date = request.POST['start_date']
                campaign.end_date = request.POST['end_date']
                campaign.budget = request.POST.get('budget') or None
                campaign.target_impressions = request.POST.get('target_impressions') or None
                campaign.save()
                
                # Log activity
                ActivityLog.objects.create(
                    user=request.user,
                    action='UPDATE',
                    content_type='Campaign',
                    object_id=campaign.id,
                    description=f'Updated campaign: {campaign.name}'
                )
                
                messages.success(request, f'Campaign "{campaign.name}" updated successfully.')
                return redirect('campaigns:detail', campaign_id=campaign.id)
                
        except Exception as e:
            messages.error(request, f'Error updating campaign: {str(e)}')
    
    # Get form data
    brands = Brand.objects.filter(is_active=True).order_by('name')
    agencies = Agency.objects.filter(is_active=True).order_by('name')
    
    context = {
        'campaign': campaign,
        'brands': brands,
        'agencies': agencies,
        'campaign_types': Campaign.CAMPAIGN_TYPES,
        'is_edit': True,
    }
    
    return render(request, 'campaigns/campaign_form.html', context)


@login_required
@require_http_methods(["POST"])
def campaign_approve(request, campaign_id):
    """Approve a campaign."""
    campaign = get_object_or_404(Campaign, id=campaign_id)
    
    if not request.user.profile.can_manage_campaigns():
        messages.error(request, 'You do not have permission to approve campaigns.')
        return redirect('campaigns:detail', campaign_id=campaign.id)
    
    campaign.approve(request.user)
    
    # Log activity
    ActivityLog.objects.create(
        user=request.user,
        action='APPROVE',
        content_type='Campaign',
        object_id=campaign.id,
        description=f'Approved campaign: {campaign.name}'
    )
    
    messages.success(request, f'Campaign "{campaign.name}" approved successfully.')
    return redirect('campaigns:detail', campaign_id=campaign.id)


@login_required
def creative_list(request):
    """List all creatives with filtering."""
    creatives = Creative.objects.all()
    
    # Filtering
    search = request.GET.get('search')
    if search:
        creatives = creatives.filter(name__icontains=search)
    
    creative_type = request.GET.get('type')
    if creative_type:
        creatives = creatives.filter(creative_type=creative_type)
    
    approved = request.GET.get('approved')
    if approved == 'true':
        creatives = creatives.filter(is_approved=True)
    elif approved == 'false':
        creatives = creatives.filter(is_approved=False)
    
    # Pagination
    paginator = Paginator(creatives, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'creative_types': Creative.CREATIVE_TYPES,
        'current_search': search,
        'current_type': creative_type,
        'current_approved': approved,
    }
    
    return render(request, 'campaigns/creative_list.html', context)


@login_required
def creative_upload(request):
    """Upload a new creative."""
    if request.method == 'POST':
        try:
            creative = Creative.objects.create(
                name=request.POST['name'],
                creative_type=request.POST['creative_type'],
                file=request.FILES['file'],
                duration=request.POST.get('duration') or None,
                width=request.POST.get('width') or None,
                height=request.POST.get('height') or None,
                bitrate=request.POST.get('bitrate') or None,
            )
            
            # Auto-approve if user has permission
            if request.user.profile.can_manage_campaigns():
                creative.is_approved = True
                creative.approved_by = request.user
                creative.approved_at = timezone.now()
                creative.save()
            
            # Log activity
            ActivityLog.objects.create(
                user=request.user,
                action='CREATE',
                content_type='Creative',
                object_id=creative.id,
                description=f'Uploaded creative: {creative.name}'
            )
            
            messages.success(request, f'Creative "{creative.name}" uploaded successfully.')
            return redirect('campaigns:creative_list')
            
        except Exception as e:
            messages.error(request, f'Error uploading creative: {str(e)}')
    
    context = {
        'creative_types': Creative.CREATIVE_TYPES,
    }
    
    return render(request, 'campaigns/creative_upload.html', context)


@login_required
def campaign_stats_api(request, campaign_id):
    """API endpoint for campaign statistics."""
    campaign = get_object_or_404(Campaign, id=campaign_id)
    
    # Get date range
    days = int(request.GET.get('days', 30))
    end_date = timezone.now().date()
    start_date = end_date - timezone.timedelta(days=days)
    
    # Get daily stats
    daily_stats = []
    current_date = start_date
    
    while current_date <= end_date:
        day_impressions = campaign.adspots.filter(
            history__executed_at__date=current_date
        ).aggregate(Sum('history__impressions'))['history__impressions__sum'] or 0
        
        daily_stats.append({
            'date': current_date.isoformat(),
            'impressions': day_impressions,
        })
        
        current_date += timezone.timedelta(days=1)
    
    return JsonResponse({
        'daily_stats': daily_stats,
        'total_impressions': campaign.total_impressions,
        'total_adspots': campaign.adspots.count(),
    })