from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db import transaction
from django.utils import timezone
from decimal import Decimal
from django.db.models import Q
from django.contrib.admin.views.decorators import staff_member_required

from .models import (
    User, Alumni, AlumniCategory, AlumniChapter,
    AcademicHistory, Employment,SystemLog,Job,
    AlumniEvent, EventParticipation, Donation,MediaResources
)

import uuid
import requests
from django.conf import settings
from .utils import log_system_event,send_sms,normalize_phone
from django.urls import reverse
from django.core.paginator import Paginator
from django.db.models import Count, Sum
from django.db.models.functions import ExtractYear
from django.contrib.auth import get_user_model
from django.core.mail import send_mail
from django.template.loader import render_to_string
from .forms import AlumniUpdateForm, AcademicHistoryFormSet, EmploymentFormSet
from django.http import FileResponse


def download_file(request, pk):
    resource = MediaResources.objects.get(pk=pk)
    return FileResponse(resource.file.open(), as_attachment=True)


def job_list(request):
    jobs = Job.objects.filter(
        is_active=True,
        deadline__gte=now().date()
    ).order_by("-created_at")

    # Filtering
    job_type = request.GET.get("job_type")
    location = request.GET.get("location")
    company = request.GET.get("company")

    if job_type:
        jobs = jobs.filter(job_type=job_type)
    if location:
        jobs = jobs.filter(location__icontains=location)
    if company:
        jobs = jobs.filter(company__icontains=company)

    # Pagination
    paginator = Paginator(jobs, 10)  
    page_number = request.GET.get("page")
    page_obj = paginator.get_page(page_number)

    context = {
        "page_obj": page_obj,
        "filter_values": {
            "job_type": job_type or "",
            "location": location or "",
            "company": company or "",
        }
    }

    return render(request, "jobs/job_list.html", context)

def job_detail(request, pk):
    job = get_object_or_404(Job, pk=pk, is_active=True)

    return render(request, "jobs/job_detail.html", {"job": job})


def alumni_donation_statistics(request):

    # =============================
    # Alumni Grouped by Registration Year
    # =============================
    alumni_by_registration = (
        Alumni.objects
        .annotate(year=ExtractYear('date_registered'))
        .values('year')
        .annotate(total=Count('id'))
        .order_by('year')
    )

    # =============================
    # Alumni Grouped by Graduation Year
    # =============================
    alumni_by_graduation = (
        AcademicHistory.objects
        .values('year_completed')
        .annotate(total=Count('alumni', distinct=True))
        .order_by('year_completed')
    )

    # =============================
    # Donations Grouped by Year (SUCCESS only)
    # =============================
    donations_by_year = (
        Donation.objects
        .filter(status='SUCCESS')
        .annotate(year=ExtractYear('created_at'))
        .values('year')
        .annotate(
            total_amount=Sum('amount'),
            total_count=Count('id')
        )
        .order_by('year')
    )

    # =============================
    # Summary Totals
    # =============================
    total_alumni = Alumni.objects.count()

    active_alumni = Alumni.objects.filter(is_active=True).count()

    total_donations = Donation.objects.filter(status='SUCCESS').count()

    total_amount = Donation.objects.filter(
        status='SUCCESS'
    ).aggregate(total=Sum('amount'))['total'] or 0

    context = {
        "alumni_by_registration": list(alumni_by_registration),
        "alumni_by_graduation": list(alumni_by_graduation),
        "donations_by_year": list(donations_by_year),
        "total_alumni": total_alumni,
        "active_alumni": active_alumni,
        "total_donations": total_donations,
        "total_amount": total_amount,
    }

    return render(request, "alumni/statistics.html", context)




@login_required
def system_logs(request):
    # Restrict to staff/admin only
    if not request.user.is_staff:
        messages.error(request, "Unauthorized access.")
        return redirect("alumni:dashboard")

    logs = SystemLog.objects.all().order_by("-created_at")

    # Search functionality
    search_query = request.GET.get("q")
    if search_query:
        logs = logs.filter(
            Q(user__icontains=search_query) |
            Q(action_type__icontains=search_query) |
            Q(description__icontains=search_query)
        )

    #  Filter by action type
    action_filter = request.GET.get("action")
    if action_filter:
        logs = logs.filter(action_type=action_filter)

    # Pagination
    paginator = Paginator(logs, 20)  # 20 logs per page
    page_number = request.GET.get("page")
    page_obj = paginator.get_page(page_number)

    context = {
        "page_obj": page_obj,
        "search_query": search_query,
        "action_filter": action_filter,
    }

    return render(request, "alumni/system_logs.html", context)


@staff_member_required
def donation_audit_report(request):
    """
    Admin view to display donation audit report
    """

    # Filters
    status_filter = request.GET.get("status", "")
    search_query = request.GET.get("q", "")

    donations = Donation.objects.all().order_by("-created_at")

    if status_filter:
        donations = donations.filter(status=status_filter.upper())

    if search_query:
        donations = donations.filter(
            Q(reference__icontains=search_query) |
            Q(user__email__icontains=search_query) |
            Q(user__username__icontains=search_query)
        )

    context = {
        "donations": donations,
        "status_filter": status_filter,
        "search_query": search_query,
    }

    return render(request, "admin/donation_audit_report.html", context)

@login_required
def donate(request):

    if request.method == "POST":
        amount = request.POST.get("amount")
        phone_number = request.POST.get("phone_number")

        # Basic validation
        if not amount:
            messages.error(request, "Please enter donation amount.")
            return redirect("alumni:donate")

        try:
            amount = Decimal(amount)

            if amount <= 0:
                raise ValueError("Invalid amount")

        except ValueError:
            messages.error(request, "Invalid donation amount.")
            return redirect("alumni:donate")

        reference_id = str(uuid.uuid4())
        reference = f'UBIDS_AMS_{reference_id}'

        donation = Donation.objects.create(
            user=request.user,
            amount=amount,
            phone_number=phone_number,
            reference=reference,
            status="PENDING"
        )

        log_system_event(
            user=request.user,
            action_type='DONATION_INIT',
            description=f"Donation initialized. Ref: {reference}, Amount: {amount}",
            request=request
        )

        url = "https://api.paystack.co/transaction/initialize"

        headers = {
            "Authorization": f"Bearer {settings.PAYSTACK_SECRET_KEY}",
            "Content-Type": "application/json",
        }
        
        callback_url = request.build_absolute_uri(reverse("alumni:verify_payment", args=[reference]))
        
        data = {
            "email": request.user.email,
            "amount": int(amount * 100),  # Kobo
            "reference": reference,
            "currency": "GHS",
            "callback_url": callback_url,
            "metadata": {
                    "system": 'UBIDS_ALUMNI_SYSTEM',
                    
                }
        }

        try:
            response = requests.post(url, json=data, headers=headers, timeout=60)
            res_data = response.json()
        except requests.exceptions.RequestException as e:

            log_system_event(
                user=request.user,
                action_type='PAYSTACK_ERROR',
                description=f"Network Error: {str(e)}",
                request=request
            )

            messages.error(request, "Payment service unavailable.")
            return redirect("alumni:donate")

        if res_data.get("status"):
            return redirect(res_data["data"]["authorization_url"])
        else:
            log_system_event(
                user=request.user,
                action_type='PAYSTACK_ERROR',
                description=str(res_data),
                request=request
            )

            messages.error(request, "Payment initialization failed.")
            return redirect("alumni:donate")

    return render(request, "donations/donate.html")


@login_required
def verify_donation(request, reference):
    donation = get_object_or_404(Donation, reference=reference)
    sms_recipient_lst = [normalize_phone(donation.phone_number)]
    print(sms_recipient_lst)

    url = f"https://api.paystack.co/transaction/verify/{reference}"
    headers = {
        "Authorization": f"Bearer {settings.PAYSTACK_SECRET_KEY}",
    }

    try:
        response = requests.get(url, headers=headers)
        response_data = response.json()

        if response_data.get("status") and response_data["data"]["status"] == "success":
            paystack_data = response_data["data"]
            paystack_amount = Decimal(response_data["data"]["amount"]) / Decimal("100")

            # Ensure amount matches and prevent double verification
            if paystack_amount == donation.amount and donation.status != "SUCCESS":
                donation.status = "SUCCESS"
                donation.transaction_id = paystack_data.get("id")
                donation.payment_channel = paystack_data.get("channel")
                donation.gateway_response = paystack_data.get("gateway_response")
                donation.paid_at = paystack_data.get("paid_at")
            
                donation.save()
                
                log_system_event(
                    user=donation.user,
                    action_type="DONATION_VERIFIED",
                    description=f"Donation verified successfully. Ref: {reference}",
                    request=request
                )

                messages.success(request, "Donation verified successfully. Thank you!")
                
                message = (
                   
                    f"your donation of GHS {donation.amount} "
                    f"was successful. Ref: {donation.reference}. "
                    f"Thank you for supporting UBIDS Alumni."
                )
                
                try:
                    # send_sms(donation.phone_number, message)
                    apiKey=settings.MNOTIFY_API_KEY

                    url = f"{settings.MNOTIFY_ENDPOINT}?key={apiKey}"
                
                    data = {
                        "recipient": sms_recipient_lst,
                        "sender": settings.MNOTIFY_SENDER_ID,
                        "message": message,
                        "is_schedule": False,
                        "schedule_date": ""
                    }
                
                   
                    try:
                        response = requests.post(url, json=data, timeout=30)
                        result = response.json()
                        
                        print(result)
                        
                       
                
                    except requests.exceptions.RequestException as e:
                        print('sms notification is not sent')
                        print(e)
                        

                except Exception as e:
                    print(e)
                    messages.error(request, "SMS notification failed.")
                    
                
            else:
                donation.status = "FAILED"
                donation.transaction_id = paystack_data.get("id")
                donation.payment_channel = paystack_data.get("channel")
                donation.gateway_response = paystack_data.get("gateway_response")
                donation.paid_at = paystack_data.get("paid_at")
            
                donation.save()
                
                log_system_event(
                    user=donation.user,
                    action_type="DONATION_FAILED",
                    description=f"Donation Failed. Ref: {reference}",
                    request=request
                )

                messages.warning(request, "Donation already verified or amount mismatch.")
        else:
            log_system_event(
                user=donation.user,
                action_type="DONATION_VERIFICATION_FAILED",
                description=f"Donation verification failed. Ref: {reference}",
                request=request
            )

            messages.error(request, "Donation verification failed.")

    except Exception as e:
        log_system_event(
            user=donation.user,
            action_type="DONATION_VERIFY_ERROR",
            description=f"Error verifying donation: {str(e)} | Ref: {reference}",
            request=request
        )

        messages.error(request, "An error occurred during verification.")

    return redirect("alumni:donation_success", reference=reference)
    

@login_required
def donation_status(request, reference):
    """
    Display the status of a donation.
    """
    donation = get_object_or_404(Donation, reference=reference)

    return render(request, "donations/donation_success.html", {"donation": donation})



User = get_user_model()

@transaction.atomic
def alumni_register(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')
        full_name = request.POST.get('full_name')
        gender = request.POST.get('gender')
        contact_number = request.POST.get('contact_number')
        graduation_year = request.POST.get('graduation_year')
        programme = request.POST.get('programme')
        category_id = request.POST.get('category')
        chapter_id = request.POST.get('chapter')

        if User.objects.filter(email=email).exists():
            messages.error(request, "Email already exists")
            return redirect('alumni:register')

        # Create user
        user = User.objects.create_user(
            email=email,
            password=password,
            role='ALUMNI'
        )

        # Create alumni profile
        alumni = Alumni.objects.create(
            user=user,
            full_name=full_name,
            gender=gender,
            contact_number=contact_number,
            graduation_year=graduation_year,
            programme=programme,
            category_id=category_id,
            chapter_id=chapter_id
        )

        # Log event
        log_system_event(
            user=user,
            action_type="ALUMNI_REGISTRATION",
            description=f"{full_name} has successfully registered",
            request=request
        )

        # ==============================
        # SEND EMAIL NOTIFICATION
        # ==============================
        try:
            subject = "Welcome to AMS – Registration Successful"

            html_message = render_to_string(
                "alumni/alumni_registration_success.html",
                {
                    "alumni": alumni,
                    "domain": request.get_host(),
                    "protocol": "https" if request.is_secure() else "http"
                }
            )

            send_mail(
                subject,
                "Your registration was successful.",  # fallback text
                settings.DEFAULT_FROM_EMAIL,
                [email],
                html_message=html_message,
                fail_silently=False,
            )
        except Exception as e:
            print("Email sending failed:", e)

        # ==============================
        # SEND SMS NOTIFICATION
        # ==============================
        try:
            if contact_number:
                sms_api_key = settings.MNOTIFY_API_KEY
                sms_endpoint = "https://api.mnotify.com/api/sms/quick"

                data = {
                    "recipient": [contact_number],
                    "sender": settings.MNOTIFY_SENDER_ID,
                    "message": f"Hello {full_name}, your AMS registration was successful. You can now login.",
                    "is_schedule": False,
                    "schedule_date": ""
                }

                requests.post(
                    f"{sms_endpoint}?key={sms_api_key}",
                    json=data,
                    timeout=10
                )
        except Exception as e:
            print("SMS sending failed:", e)

        messages.success(request, "Registration successful. Please login.")
        return redirect('alumni:login')

    categories = AlumniCategory.objects.all()
    chapters = AlumniChapter.objects.all()
     # download_file
    media_resource = MediaResources.objects.get(file_name__icontains='REGISTRATION MANUAL')

    return render(request, 'alumni/register.html', {
        'categories': categories,
        'media_resource': media_resource,
        'chapters': chapters
    })
    
    
    
@login_required
def dashboard(request):
    if request.user.role != 'ALUMNI':
        return redirect('alumni:login')

    alumni = request.user.alumni_profile
    active_jobs_count = Job.objects.filter(is_active=True, deadline__gte=now().date()).count()

    # Latest events
    events = AlumniEvent.objects.all().order_by('-event_date')[:5]
    
    # total donations
    total_donated = Donation.objects.filter(
        user=request.user,
        status__icontains='SUCCESS'
    ).aggregate(total_amount=Sum('amount'))['total_amount'] or 0

    # Donations
    donations = Donation.objects.filter(status__icontains='SUCCESS')[:5]

    # Registered events
    participations = EventParticipation.objects.filter(
        alumni=alumni
    ).select_related('event')
    
    # download_file
    media_resource = MediaResources.objects.get(file_name__icontains='profile manual')
    


    return render(request, 'alumni/dashboard.html', {
        'alumni': alumni,
        'active_jobs_count': active_jobs_count,
        'events': events,
        'donations': donations,
        'total_donated': total_donated,
        'media_resource': media_resource,
        'participations': participations
    })




@login_required
def mark_attendance(request, participation_id):
    # Ensure user is alumni
    if request.user.role != 'ALUMNI':
        messages.error(request, "Unauthorized access.")
        return redirect('alumni:login')

    alumni = request.user.alumni_profile

    # Get participation and ensure it belongs to this alumni
    participation = get_object_or_404(
        EventParticipation,
        id=participation_id,
        alumni=alumni
    )

    # Prevent double marking
    if participation.attended:
        messages.info(request, "You have already confirmed attendance.")
        return redirect('alumni:dashboard')

    # Optional: Only allow marking after event date
    if participation.event.event_date > timezone.now().date():
        messages.warning(request, "You can only confirm attendance after the event date.")
        return redirect('alumni:dashboard')

    # Mark attendance
    participation.attended = True
    participation.save()

    messages.success(request, "Attendance confirmed successfully!")

    return redirect('alumni:dashboard')


from django.db.models import Sum, Count
from django.utils.timezone import now
from datetime import timedelta


@login_required
def admin_dashboard(request):
    if request.user.role != 'ADMIN':
        return redirect('dashboard')  # redirect non-admins

    # ===============================
    # Basic Statistics
    # ===============================
    total_alumni = Alumni.objects.count()
    active_alumni = Alumni.objects.filter(is_active=True).count()
    total_events = AlumniEvent.objects.count()
    total_donations = Donation.objects.filter(status__icontains='SUCCESS').aggregate(
        total=Sum('amount')
    )['total'] or 0

    # ===============================
    # Recent Activities
    # ===============================
    recent_registrations = Alumni.objects.order_by('-date_registered')[:5]
    recent_donations = Donation.objects.select_related('user').order_by('-created_at')[:5]
    upcoming_events = AlumniEvent.objects.filter(
        event_date__gte=now().date()
    ).order_by('event_date')[:5]

    context = {
        'total_alumni': total_alumni,
        'active_alumni': active_alumni,
        'total_events': total_events,
        'total_donations': total_donations,
        'recent_registrations': recent_registrations,
        'recent_donations': recent_donations,
        'upcoming_events': upcoming_events,
    }

    return render(request, 'alumni/admin_dashboard.html', context)


@login_required
def profile_view(request):
    """
    Display the logged-in user's profile, including personal info,
    academic history, and employment history.
    """
    try:
        alumni = request.user.alumni_profile
    except Alumni.DoesNotExist:
        # Redirect or show a message if user has no alumni profile
        return redirect('alumni:dashboard')
    # Academic and Employment records are accessed via related_name
    academic_records = alumni.academic_records.all()
    employment_records = alumni.employment_records.all()

    context = {
        'alumni': alumni,
        'academic_records': academic_records,
        'employment_records': employment_records,
    }

    return render(request, 'alumni/profile.html', context)

@login_required
def update_profile(request):
    alumni = request.user.alumni_profile

    if request.method == 'POST':
        form = AlumniUpdateForm(request.POST, request.FILES, instance=alumni)
        academic_formset = AcademicHistoryFormSet(
            request.POST,
            instance=alumni
        )
        employment_formset = EmploymentFormSet(
            request.POST,
            instance=alumni
        )

        if form.is_valid() and academic_formset.is_valid() and employment_formset.is_valid():
            form.save()
            academic_formset.save()
            employment_formset.save()

            messages.success(request, "Profile updated successfully.")
            return redirect('alumni:dashboard')
    else:
        form = AlumniUpdateForm(instance=alumni)
        academic_formset = AcademicHistoryFormSet(instance=alumni)
        employment_formset = EmploymentFormSet(instance=alumni)

    context = {
        'form': form,
        'academic_formset': academic_formset,
        'employment_formset': employment_formset,
    }

    return render(request, 'alumni/update_profile.html', context)

@login_required
def add_academic_record(request):
    alumni = request.user.alumni_profile

    if request.method == 'POST':
        AcademicHistory.objects.create(
            alumni=alumni,
            student_id=request.POST.get('student_id'),
            degree=request.POST.get('degree'),
            faculty=request.POST.get('faculty'),
            department=request.POST.get('department'),
            year_admitted=request.POST.get('year_admitted'),
            year_completed=request.POST.get('year_completed')
        )
        
        log_system_event(
            user=alumni,
            action_type="ACADEMIC_RECORDS",
            description=f"Added academic records",
            request=request
        )
        return redirect('profile')

    return render(request, 'alumni/add_academic.html')


@login_required
def add_employment(request):
    alumni = request.user.alumni_profile

    if request.method == 'POST':
        Employment.objects.create(
            alumni=alumni,
            employer=request.POST.get('employer'),
            job_title=request.POST.get('job_title'),
            industry=request.POST.get('industry'),
            employment_status=request.POST.get('employment_status'),
            start_year=request.POST.get('start_year'),
            is_current=request.POST.get('is_current') == 'on'
        )

        return redirect('profile')

    return render(request, 'alumni/add_employment.html')

@login_required
def event_list(request):
    events = AlumniEvent.objects.all()
    return render(request, 'alumni/events.html', {'events': events})


@login_required
def create_event(request):
    # Only allow admin or secretariat staff to create events
    if request.user.role not in ['ADMIN', 'SECRETARIAT']:
        messages.error(request, "You do not have permission to create events.")
        return redirect('alumni:dashboard')

    if request.method == 'POST':
        title = request.POST.get('title')
        description = request.POST.get('description')
        event_date = request.POST.get('event_date')
        location = request.POST.get('location')

        if not title or not event_date or not location:
            messages.error(request, "Title, date, and location are required.")
        else:
            AlumniEvent.objects.create(
                title=title,
                description=description,
                event_date=event_date,
                location=location
            )
            
            log_system_event(
                user = request.user,
                action_type="EVENT",
                description=f"Event created",
                request=request
            )
            messages.success(request, "Event created successfully.")
            return redirect('alumni:admin_dashboard')  # Redirect to event management page

    return render(request, 'alumni/create_event.html')



@login_required
def register_event(request, event_id):
    alumni = request.user.alumni_profile
    event = get_object_or_404(AlumniEvent, id=event_id)

    EventParticipation.objects.get_or_create(
        alumni=alumni,
        event=event
    )
    
    log_system_event(
        user = request.user,  
        action_type="EVENT",
        description=f"Registere for event",
        request=request
    )

    messages.success(request, "Successfully registered for event.")
    return redirect('alumni:dashboard')


@login_required
def event_detail(request, event_id):
    # Get the specific event or return 404 if not found
    event = get_object_or_404(AlumniEvent, id=event_id)

    return render(request, 'alumni/event_detail.html', {
        'event': event
    })

@login_required
def make_donation(request):
    alumni = request.user.alumni_profile

    if request.method == 'POST':
        Donation.objects.create(
            alumni=alumni,
            amount=request.POST.get('amount'),
            payment_reference=request.POST.get('payment_reference')
        )

        messages.success(request, "Donation recorded successfully.")
        return redirect('dashboard')

    return render(request, 'alumni/donate.html')


@login_required
def manage_events(request):
    if request.user.role != 'SECRETARIAT':
        return redirect('dashboard')

    events = AlumniEvent.objects.all()
    return render(request, 'alumni/manage_events.html', {'events': events})
