from django.shortcuts import render, redirect

# Import User
from django.contrib.auth.models import User

# Important to serialize your data to a form understandable by rest frameworks.
#from .serlializers import NoteSerializer
from rest_framework import serializers

# Codes for rest_framework installation
from rest_framework import viewsets
from rest_framework.permissions import AllowAny
from rest_framework.decorators import action
from django.http import JsonResponse, HttpResponse

#For Forms Importations
from .forms import SignupForm

#For Model Importations
from .models import Profile

#Importing lazy text 
from django.contrib import messages
from django.utils.translation import gettext_lazy as _


#Importing the django login authentifications
from django.contrib.auth import login 

#For handling db error in django
from django.db import IntegrityError

#For Cacheing
from django.core.cache import cache


import logging

logger = logging.getLogger(__name__)

#For google docs 
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import json

#For time  and date
from datetime import datetime
from django.utils import timezone




from django.views.decorators.csrf import csrf_exempt
import json
#import requests
from decimal import Decimal



####### will delete alot here# your_app/views.py

import os
import io
import json
import zipfile
import tempfile
import logging
import requests
from django.utils import timezone
from django.conf import settings
from django.shortcuts import redirect, render
from django.http import HttpResponse, JsonResponse, StreamingHttpResponse
from django.contrib import messages
from rest_framework.decorators import action
from google_auth_oauthlib.flow import Flow
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import MediaIoBaseDownload
from google.auth.transport.requests import Request



#Importation of the SignupForm
class DummySerializer(serializers.Serializer):
    #I will add some data later on...
    #Simply used to derialize the information stored in the datatabse.
    pass


class NotCloudStorage(viewsets.ModelViewSet): 
     
    @action(detail=False, methods=['get'], url_path='')
    def default_page(self, request, *args, **kwargs):
        base_domain = request.build_absolute_uri('/')
        # Check if the user is authenticated
        if request.user.is_authenticated:
            # Redirect authenticated users to the home page
            #return redirect('/home')  # Replace '/omoca/home_page/' with your actual home page URL
             
             return render(request, 'index.html',{'base_domain':base_domain})
         
        else:
            # Redirect non-authenticated users to the login page

            return render(request, 'index.html',{'base_domain':base_domain})
        
        
class NotCloudStorageViewSet(viewsets.ModelViewSet):
    permission_classes = (AllowAny,)
    serializer_class = DummySerializer
    

    @action(detail=False, methods=['GET', 'POST'], url_path=r'signup')
    def signup(self, request):
        base_domain = request.build_absolute_uri('/')
        
        # Check if user came from social auth and needs profile completion
        social_login = request.user.is_authenticated and not hasattr(request.user, 'profile')
        
        # If user is authenticated and has profile, redirect to home
        if request.user.is_authenticated and hasattr(request.user, 'profile'):
            messages.info(request, _("You are already logged in."))
            return redirect('/home/')

        if request.method == 'POST':
            if social_login:
                # Social login completion
                form = SignupForm(request.POST, social_login=True)
            else:
                # Manual registration
                form = SignupForm(request.POST)
            
            if form.is_valid():
                cleaned_data = form.cleaned_data
                email = cleaned_data['email']
                is_social_login = cleaned_data.get('social_login', False)
                
                try:
                    if is_social_login and request.user.is_authenticated:
                        # Social login completion
                        user = request.user
                        
                        # Update user email if different
                        if user.email != email:
                            user.email = email
                            user.save()
                        
                        # Create profile
                        profile, created = Profile.objects.get_or_create(
                            user=user,
                            defaults={
                                'email': email,
                                'agreed_to_terms': cleaned_data['agreed_to_terms']
                            }
                        )
                        
                        if created:
                            messages.success(request, _("Account setup complete! Welcome to our platform!"))
                        else:
                            messages.info(request, _("Welcome back!"))
                        
                        return redirect('/home/')
                        
                    else:
                        # Manual registration
                        if User.objects.filter(email=email).exists():
                            emailError = _("An account with this email already exists. Please log in instead.")
                            return render(request, 'signup.html', {
                                'form': form, 
                                'emailError': emailError, 
                                'base_domain': base_domain
                            })
                        
                        # Create user with unique username
                        username = email
                        counter = 1
                        while User.objects.filter(username=username).exists():
                            username = f"{email.split('@')[0]}{counter}"
                            counter += 1
                        
                        user = User.objects.create_user(
                            username=username,
                            email=email,
                            password=cleaned_data['password1']
                        )
                        
                        # Create profile
                        Profile.objects.create(
                            user=user,
                            email=email,
                            agreed_to_terms=cleaned_data['agreed_to_terms']
                        )
                        
                        messages.success(request, _("Account created successfully! Please log in to continue."))
                        return redirect(f'{base_domain}login/')

                except IntegrityError as e:
                    logger.error(f"IntegrityError during signup: {e}")
                    messages.error(request, _("There was an error creating your account. Please try again."))
                except Exception as e:
                    logger.error(f"Error during signup: {e}")
                    messages.error(request, _("An unexpected error occurred. Please try again."))

            else:
                # Form validation failed
                return render(request, 'signup.html', {
                    'form': form,
                    'emailError': "",
                    'base_domain': base_domain
                })

        else:
            # GET request
            if social_login:
                # Pre-populate for social auth completion
                form = SignupForm(initial={
                    'email': request.user.email,
                    'social_login': True
                }, social_login=True)
            else:
                form = SignupForm()
            
            return render(request, 'signup.html', {
                'form': form, 
                'emailError': "", 
                'base_domain': base_domain
            }) 

            
    @action(detail=False, methods=['get', 'POST'], url_path=r'login')
    def admin_login(self, request):
        base_domain = request.build_absolute_uri('/')
        
        # If user is already authenticated, redirect to home
        if request.user.is_authenticated:
            messages.info(request, _("You are already logged in."))
            return redirect(f'{base_domain}home/')
        
        if request.method == "POST":
            email = request.POST.get('username')
            password = request.POST.get('password')
            
            if email and password:
                user = User.objects.filter(email=email).first()
                if user:
                    if user.check_password(password):
                        login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                        messages.success(request, _("Welcome back! You have been successfully logged in."))
                        return redirect(f'{base_domain}home/')
                    else:
                        messages.error(request, _("Invalid password. Please try again."))
                else:
                    messages.error(request, _("Invalid email or password. Please try again."))
            else:
                messages.error(request, _("Please enter both email and password."))
        
        return render(request, 'login.html', {'base_domain': base_domain})
        
    
    @action(detail=False, methods=['get'], url_path=r'home')
    def home(self, request):
        base_domain = request.build_absolute_uri('/')
        user = request.user
        
        # Sample data for authenticated users (you'll replace this with real data)
        context = {
            'base_domain': base_domain,
            'user': user,
        }
        
        # Add user-specific data if authenticated
        if user.is_authenticated:
            # You'll replace these with actual database queries
            context.update({
                'user_orders': [],  # Will be actual orders from database
                'user_stats': {},   # Will be actual stats from database
            })
        
        return render(request, 'index.html', context)
    
    
    @action(detail=False, methods=['get'], url_path=r'logout')
    def logout(self, request):
        from django.contrib.auth import logout
        from django.contrib import messages
        
        # Log the user out
        logout(request)
        
        # Add a success message
        messages.success(request, _("You have been successfully logged out."))
        
        # Redirect to login page or home page
        base_domain = request.build_absolute_uri('/')
        return redirect(f'{base_domain}login/')
        
    

########## CONNECTING CLOUD ACCOUNTS AND FILE SELECTION WITH REAL GOOGLE DRIVE API ##########
    @action(detail=False, methods=['get', 'post'], url_path=r'transfer/cloud-connect')
    def cloud_connect(self, request):
        """Step 1: Cloud Account Connection with Real Google Drive API"""
        base_domain = request.build_absolute_uri('/')
        user = request.user
        
        if not user.is_authenticated:
            return redirect(f'{base_domain}login/')
        
        context = {
            'base_domain': base_domain,
            'user': user,
            'current_step': 1,
            'cloud_services': self._get_cloud_services_info(user)
        }
        
        if request.method == 'POST':
            cloud_source = request.POST.get('cloud_source')
            if cloud_source in ['google_drive', 'dropbox', 'onedrive']:
                if cloud_source == 'google_drive':
                    # Initiate Google OAuth flow
                    request.session['selected_cloud'] = "google_drive"
                    return redirect(f'{base_domain}oauth/login/google-oauth2/?next={base_domain}transfer/new/')
                else:
                    # For other services, store selection and proceed
                    request.session['selected_cloud'] = cloud_source
                    request.session['cloud_connected'] = True
                    messages.info(request, f"{cloud_source.replace('_', ' ').title()} connection initiated")
                    print("I SHOULD GO TO THE TRANSFER WINDOW")
                    return redirect(f'{base_domain}transfer/new/')
            else:
                messages.error(request, "Please select a valid cloud service")
        
        return render(request, 'transfer.html', context)

    def _get_cloud_services_info(self, user):
        """Get real Google Drive info and dummy data for other services"""
        google_drive_info = self._get_google_drive_info(user)
        
        return [
            google_drive_info,
            
            #Replace with real API calls for Dropbox
            {
                'id': 'dropbox',
                'name': 'Dropbox',
                'icon': 'dropbox',
                'brand_color': '#0061FF',
                'description': 'Access files from your Dropbox account',
                'storage_quota': '2 GB free, upgradable',
                'features': ['File sharing', 'Version history', 'Team folders'],
                'connected': False,
                'account_email': None,
                'used_storage': '0 GB',
                'total_storage': '2 GB',
                'file_count': 0
            },
            
             #Replace with real API calls for Onedrive
            {
                'id': 'onedrive',
                'name': 'OneDrive',
                'icon': 'microsoft',
                'brand_color': '#0078D4',
                'description': 'Access files from your Microsoft OneDrive',
                'storage_quota': '5 GB free',
                'features': ['Office Online', 'Personal vault', 'File sharing'],
                'connected': False,
                'account_email': None,
                'used_storage': '0 GB',
                'total_storage': '5 GB',
                'file_count': 0
            }
        ] 
        
    def _get_google_drive_info(self, user):
        """Get real Google Drive information using the Google Drive API"""
        try:
            # Check if user has Google OAuth connected
            from social_django.models import UserSocialAuth
            social_auth = UserSocialAuth.objects.filter(
                user=user, 
                provider='google-oauth2'
            ).first()
            
            if social_auth:
                # Get access token from social auth
                access_token = social_auth.extra_data.get('access_token')
                
                if access_token:
                    # Create credentials object
                    credentials = Credentials(token=access_token)
                    
                    print("Access Token:", access_token)
                    
                    # Build Google Drive service
                    service = build('drive', 'v3', credentials=credentials)
                    
                    # Get storage quota
                    about = service.about().get(fields="storageQuota,user").execute()
                    storage_quota = about.get('storageQuota', {})
                    user_info = about.get('user', {})
                    
                    # Get file count
                    files = service.files().list(
                        pageSize=1,
                        fields="files(id,name),nextPageToken"
                    ).execute()
                    
                    # Calculate file count (approximate)
                    file_count = self._get_google_drive_file_count(service)
                    
                    # Format storage info
                    used_bytes = int(storage_quota.get('usage', 0))
                    total_bytes = int(storage_quota.get('limit', 0))
                    
                    used_gb = self._bytes_to_gb(used_bytes)
                    total_gb = self._bytes_to_gb(total_bytes)
                    usage_percentage = (used_bytes / total_bytes * 100) if total_bytes > 0 else 0
                    
                    return {
                        'id': 'google_drive',
                        'name': 'Google Drive',
                        'icon': 'google-drive',
                        'brand_color': '#4285F4',
                        'description': 'Access files from your Google Drive account',
                        'storage_quota': f'{total_gb} GB total',
                        'features': ['Docs, Sheets, Slides', 'Photo backup', 'Team drives'],
                        'connected': True,
                        'account_email': user_info.get('emailAddress', 'Connected'),
                        'used_storage': f'{used_gb:.1f} GB',
                        'total_storage': f'{total_gb} GB',
                        'usage_percentage': round(usage_percentage, 1),
                        'file_count': file_count,
                        'storage_details': {
                            'used_bytes': used_bytes,
                            'total_bytes': total_bytes,
                            'used_gb': used_gb,
                            'total_gb': total_gb
                        }
                    }
            
            # Fallback for users without Google OAuth or if API call fails
            return {
                'id': 'google_drive',
                'name': 'Google Drive',
                'icon': 'google-drive',
                'brand_color': '#4285F4',
                'description': 'Access files from your Google Drive account',
                'storage_quota': 'Connect to view storage',
                'features': ['Docs, Sheets, Slides', 'Photo backup', 'Team drives'],
                'connected': False,
                'account_email': None,
                'used_storage': '0 GB',
                'total_storage': '0 GB',
                'file_count': 0
            }
            
        except HttpError as error:
            print(f"Google Drive API error: {error}")
            # Return disconnected state on API error
            return {
                'id': 'google_drive',
                'name': 'Google Drive',
                'icon': 'google-drive',
                'brand_color': '#4285F4',
                'description': 'Access files from your Google Drive account',
                'storage_quota': 'Reconnect required',
                'features': ['Docs, Sheets, Slides', 'Photo backup', 'Team drives'],
                'connected': False,
                'account_email': None,
                'used_storage': '0 GB',
                'total_storage': '0 GB',
                'file_count': 0
            }
        except Exception as error:
            print(f"Unexpected error: {error}")
            return {
                'id': 'google_drive',
                'name': 'Google Drive',
                'icon': 'google-drive',
                'brand_color': '#4285F4',
                'description': 'Access files from your Google Drive account',
                'storage_quota': 'Connection error',
                'features': ['Docs, Sheets, Slides', 'Photo backup', 'Team drives'],
                'connected': False,
                'account_email': None,
                'used_storage': '0 GB',
                'total_storage': '0 GB',
                'file_count': 0
            }

    def _get_google_drive_file_count(self, service):
        """Get approximate file count from Google Drive"""
        try:
            # This gets a rough count - for exact count you'd need to paginate through all files
            result = service.files().list(
                pageSize=1000,
                fields="nextPageToken, files(id, name)"
            ).execute()
            
            files = result.get('files', [])
            return len(files)
        except:
            return 0

    def _bytes_to_gb(self, bytes_value):
        """Convert bytes to gigabytes"""
        return bytes_value / (1024 ** 3)



    ##### NOW HANDLING THE FILE SELECTION WITH REAL GOOGLE DRIVE API ##########
    @action(detail=False, methods=['get', 'post'], url_path=r'transfer/new')
    def new_transfer(self, request):
        
        """Step 2: File Selection with Google Drive API"""
        base_domain = request.build_absolute_uri('/')
        user = request.user
         
        if not user.is_authenticated:
            return redirect(f'{base_domain}login/')
        
        # Check if cloud is connected
        cloud_source = request.session.get('selected_cloud')
        
        if not cloud_source:
            messages.error(request, "Please connect a cloud account first")
            return redirect(f'{base_domain}transfer/cloud-connect/')
        
        context = {
            'base_domain': base_domain,
            'user': user,
            'cloud_source': cloud_source,
            'current_step': 2
        }
        
        if request.method == 'POST':
            selected_files = request.POST.getlist('selected_files')
            
            if not selected_files:
                messages.error(request, "Please select at least one file to transfer")
                return self._render_file_selection(request, context, cloud_source, user)
            
            try:
                # Create transfer order
                order = self._create_transfer_order(request, user, cloud_source, selected_files)
                request.session['current_order_id'] = str(order.id)
                
                #request.session['current_order_id'] = str(order.id)  # Convert UUID to string
                request.session.modified = True
                
                return redirect(f'{base_domain}transfer/storage/')
                
            except Exception as e:
                messages.error(request, f"Error creating transfer: {str(e)}")
                print(f"Transfer creation error: {e}")
        
        # GET request - show file browser for selected cloud
        return self._render_file_selection(request, context, cloud_source, user)


    #This renders all the files from the selected cloud service
    def _render_file_selection(self, request, context, cloud_source, user):
        """Render file selection page for specific cloud with real Google Drive API"""
        cloud_data = self._get_cloud_data(cloud_source, user) #This is where am getting the real data from the cloud services.
        context.update(cloud_data) #Contains the previous data plus the cloud data.
        return render(request, 'transfer.html', context)
    
    
    #Gets the cloud data based on the user, may vary for all the cloud providers.
    def _get_cloud_data(self, cloud_source, user):
        """Get cloud-specific data structure with real Google Drive API"""
        if cloud_source == 'google_drive':
            return self._get_google_drive_data(user)
        elif cloud_source == 'dropbox':
            return self._get_dropbox_data()
        elif cloud_source == 'onedrive':
            return self._get_onedrive_data()
        else:
            return {}
        
        
    #Gets now google drive data exactly.
    def _get_google_drive_data(self, user):
        """Google Drive API structure with real data"""
        try:
            from social_django.models import UserSocialAuth
            from google.oauth2.credentials import Credentials
            from googleapiclient.discovery import build
            from googleapiclient.errors import HttpError
            
            # Check if user has Google OAuth connected
            social_auth = UserSocialAuth.objects.filter(
                user=user, 
                provider='google-oauth2'
            ).first()
            
            if not social_auth or not social_auth.extra_data.get('access_token'):
                return {
                    'cloud_connected': False,
                    'cloud_service': 'Google Drive',
                    'user_email': 'Not connected',
                    'storage_info': {
                        'used': '0 GB',
                        'total': '0 GB',
                        'percentage': 0,
                        'available': '0 GB',
                        'quota_type': 'free'
                    },
                    'files': [],
                    'categories': [],
                    'total_files': 0,
                    'total_size': '0 GB',
                    'error': 'Please reconnect your Google Drive account'
                }
            
            # Create credentials and service
            credentials = Credentials(token=social_auth.extra_data.get('access_token'))
            service = build('drive', 'v3', credentials=credentials)
            
            # Get storage info
            about = service.about().get(fields="storageQuota,user").execute()
            storage_quota = about.get('storageQuota', {})
            user_info = about.get('user', {})
            
            used_bytes = int(storage_quota.get('usage', 0))
            total_bytes = int(storage_quota.get('limit', 0))
            used_gb = self._bytes_to_gb(used_bytes)
            total_gb = self._bytes_to_gb(total_bytes)
            usage_percentage = (used_bytes / total_bytes * 100) if total_bytes > 0 else 0
            
            # Get real files from Google Drive
            files = self._get_real_google_drive_files(service)
            
            # Get file categories
            categories = self._get_google_drive_categories(service)
            
            return {
                'cloud_connected': True,
                'cloud_service': 'Google Drive',
                'user_email': user_info.get('emailAddress', 'notconnected@gmail.com'),
                'storage_info': {
                    'used': f'{used_gb:.1f} GB',
                    'total': f'{total_gb:.0f} GB',
                    'percentage': round(usage_percentage, 1),
                    'available': f'{total_gb - used_gb:.1f} GB',
                    'quota_type': 'free' if total_gb <= 15 else 'premium'
                },
                'files': files,
                'categories': categories,
                'total_files': len(files),
                'total_size': f'{used_gb:.1f} GB'
            }
            
        except HttpError as error:
            print(f"Google Drive API error in file selection: {error}")
            return {
                'cloud_connected': False,
                'cloud_service': 'Google Drive',
                'user_email': 'Connection error',
                'storage_info': {
                    'used': '0 GB',
                    'total': '0 GB',
                    'percentage': 0,
                    'available': '0 GB',
                    'quota_type': 'free'
                },
                'files': [],
                'categories': [],
                'total_files': 0,
                'total_size': '0 GB',
                'error': 'Failed to load Google Drive files. Please try again.'
            }
        except Exception as error:
            print(f"Unexpected error in Google Drive data: {error}")
            return {
                'cloud_connected': False,
                'cloud_service': 'Google Drive',
                'user_email': 'Error',
                'storage_info': {
                    'used': '0 GB',
                    'total': '0 GB',
                    'percentage': 0,
                    'available': '0 GB',
                    'quota_type': 'free'
                },
                'files': [],
                'categories': [],
                'total_files': 0,
                'total_size': '0 GB',
                'error': 'An unexpected error occurred.'
            }

    def _get_real_google_drive_files(self, service):
        """Get real files from Google Drive API"""
        try:
            
            # Get files from Google Drive
            results = service.files().list(
                pageSize=500,  # Limit to 50 files for performance
                fields="nextPageToken, files(id, name, mimeType, size, modifiedTime, createdTime, webViewLink)",
                orderBy="modifiedTime desc"
            ).execute()
            
            
            files = results.get('files', [])
            formatted_files = []
            
            for file in files:
                # Skip app data folders and shortcuts
                if file.get('mimeType') == 'application/vnd.google-apps.shortcut':
                    continue
                    
                # Format file size
                size_bytes = int(file.get('size', 0))
                if size_bytes < 1024:
                    size_display = f"{size_bytes} B"
                elif size_bytes < 1024 * 1024:
                    size_display = f"{size_bytes / 1024:.1f} KB"
                elif size_bytes < 1024 * 1024 * 1024:
                    size_display = f"{size_bytes / (1024 * 1024):.1f} MB"
                else:
                    size_display = f"{size_bytes / (1024 * 1024 * 1024):.1f} GB"
                
                # Format modified time
                modified_time = file.get('modifiedTime')
                mod_display = "Unknown"
                if modified_time:
                    try:
                        mod_date = datetime.fromisoformat(modified_time.replace('Z', '+00:00'))
                        now = datetime.now(timezone.utc)
                        diff = now - mod_date
                        
                        if diff.days == 0:
                            if diff.seconds < 60:
                                mod_display = "Just now"
                            elif diff.seconds < 3600:
                                mod_display = f"{diff.seconds // 60} minutes ago"
                            else:
                                mod_display = f"{diff.seconds // 3600} hours ago"
                        elif diff.days == 1:
                            mod_display = "1 day ago"
                        elif diff.days < 7:
                            mod_display = f"{diff.days} days ago"
                        elif diff.days < 30:
                            mod_display = f"{diff.days // 7} weeks ago"
                        else:
                            mod_display = mod_date.strftime("%b %d, %Y")
                    except:
                        mod_display = "Unknown"
                
                # Determine file type and icon
                mime_type = file.get('mimeType', '')
                is_folder = mime_type == 'application/vnd.google-apps.folder'
                
                formatted_files.append({
                    'id': file['id'],
                    'name': file['name'],
                    'size': size_display,
                    'sizeBytes': size_bytes,
                    'mimeType': mime_type,
                    'modified_display': mod_display,
                    'folder': is_folder,
                    'webViewLink': file.get('webViewLink', ''),
                    'item_count': 'Multiple items' if is_folder else None
                })
            
            return formatted_files
            
        except Exception as e:
            print(f"Error getting Google Drive files: {e}")
            # Return empty list on error
            return []      

    def _get_google_drive_categories(self, service):
        """Get real file categories from Google Drive by analyzing actual files"""
        try:
            # Get a sample of files to analyze
            results = service.files().list(
                pageSize=100,
                fields="files(mimeType, size)",
                q="trashed=false"
            ).execute()
            
            files = results.get('files', [])
            
            # Initialize category counters
            categories = {
                'documents': {'name': 'Documents', 'count': 0, 'icon': 'file-text', 'color': 'blue'},
                'images': {'name': 'Images', 'count': 0, 'icon': 'image', 'color': 'purple'},
                'videos': {'name': 'Videos', 'count': 0, 'icon': 'video', 'color': 'red'},
                'pdfs': {'name': 'PDFs', 'count': 0, 'icon': 'file-pdf', 'color': 'red'},
                'spreadsheets': {'name': 'Sheets', 'count': 0, 'icon': 'file-excel', 'color': 'green'},
                'presentations': {'name': 'Slides', 'count': 0, 'icon': 'file-powerpoint', 'color': 'orange'},
                'audio': {'name': 'Audio', 'count': 0, 'icon': 'music', 'color': 'indigo'},
                'archives': {'name': 'Archives', 'count': 0, 'icon': 'archive', 'color': 'yellow'},
                'others': {'name': 'Others', 'count': 0, 'icon': 'file', 'color': 'gray'}
            }
            
            for file in files:
                mime_type = file.get('mimeType', '')
                
                # Categorize by MIME type
                if 'application/vnd.google-apps.document' in mime_type:
                    categories['documents']['count'] += 1
                elif 'application/vnd.google-apps.spreadsheet' in mime_type:
                    categories['spreadsheets']['count'] += 1
                elif 'application/vnd.google-apps.presentation' in mime_type:
                    categories['presentations']['count'] += 1
                elif 'application/pdf' in mime_type:
                    categories['pdfs']['count'] += 1
                elif mime_type.startswith('image/'):
                    categories['images']['count'] += 1
                elif mime_type.startswith('video/'):
                    categories['videos']['count'] += 1
                elif mime_type.startswith('audio/'):
                    categories['audio']['count'] += 1
                elif any(ext in mime_type for ext in ['zip', 'rar', 'tar', '7z']):
                    categories['archives']['count'] += 1
                elif mime_type not in ['application/vnd.google-apps.folder', 'application/vnd.google-apps.shortcut']:
                    categories['others']['count'] += 1
            
            # Filter out empty categories and return only non-zero counts
            result = []
            for category in categories.values():
                if category['count'] > 0:
                    result.append(category)
            
            # Sort by count (descending)
            result.sort(key=lambda x: x['count'], reverse=True)
            
            return result
            
        except Exception as e:
            print(f"Error analyzing Google Drive categories: {e}")
            # Fallback to basic categories
            return [
                {'name': 'Documents', 'count': 0, 'icon': 'file-text', 'color': 'blue'},
                {'name': 'Images', 'count': 0, 'icon': 'image', 'color': 'purple'},
                {'name': 'Videos', 'count': 0, 'icon': 'video', 'color': 'red'},
                {'name': 'PDFs', 'count': 0, 'icon': 'file-pdf', 'color': 'red'},
            ]

    
    #For Dropbox Dummy Data For Now.
    def _get_dropbox_data(self):
        """Dropbox API structure (dummy data)"""
        return {
            'cloud_connected': True,
            'cloud_service': 'Dropbox',
            'user_email': 'user@domain.com',
            'storage_info': {
                'used': '1.4 GB',
                'total': '2 GB',
                'percentage': 70,
                'available': '0.6 GB',
                'quota_type': 'free'
            },
            'files': self._get_dropbox_files(),
            'categories': self._get_dropbox_categories(),
            'total_files': 543,
            'total_size': '1.4 GB'
        }

    def _get_dropbox_files(self):
        """Dummy Dropbox files"""
        return [
            {
                'id': 'db_file_1',
                'name': 'Project Proposal.docx',
                'size': '2.1 MB',
                'sizeBytes': 2202009,
                'mimeType': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'modified_display': '2 hours ago',
                'folder': False
            },
            {
                'id': 'db_file_2',
                'name': 'Vacation Photos',
                'size': '156.3 MB',
                'sizeBytes': 163877683,
                'mimeType': 'folder',
                'modified_display': '1 day ago',
                'folder': True,
                'item_count': 24
            }
        ]

    def _get_dropbox_categories(self):
        """Dummy Dropbox categories"""
        return [
            {'name': 'Documents', 'count': 45, 'icon': 'file-text', 'color': 'blue'},
            {'name': 'Photos', 'count': 123, 'icon': 'image', 'color': 'purple'},
        ]

    
    
    #For Onedrive Dummy Data For Now.
    def _get_onedrive_data(self):
        """OneDrive API structure (dummy data)"""
        return {
            'cloud_connected': True,
            'cloud_service': 'OneDrive',
            'user_email': 'user@outlook.com',
            'storage_info': {
                'used': '3.2 GB',
                'total': '5 GB',
                'percentage': 64,
                'available': '1.8 GB',
                'quota_type': 'free'
            },
            'files': self._get_onedrive_files(),
            'categories': self._get_onedrive_categories(),
            'total_files': 892,
            'total_size': '3.2 GB'
        }

    def _get_onedrive_files(self):
        """Dummy OneDrive files"""
        return [
            {
                'id': 'od_file_1',
                'name': 'Budget Spreadsheet.xlsx',
                'size': '3.8 MB',
                'sizeBytes': 3984588,
                'mimeType': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'modified_display': '5 hours ago',
                'folder': False
            },
            {
                'id': 'od_file_2',
                'name': 'Work Documents',
                'size': '890.2 MB',
                'sizeBytes': 933232435,
                'mimeType': 'folder',
                'modified_display': '3 days ago',
                'folder': True,
                'item_count': 67
            }
        ]

    def _get_onedrive_categories(self):
        """Dummy OneDrive categories"""
        return [
            {'name': 'Documents', 'count': 234, 'icon': 'file-text', 'color': 'blue'},
            {'name': 'Pictures', 'count': 89, 'icon': 'image', 'color': 'purple'},
            {'name': 'Videos', 'count': 12, 'icon': 'video', 'color': 'red'},
        ]

    
  
    # Google Drive Files (based on Drive v3 API)
    def _get_google_drive_files(self):
        return [
            # Folders (mimeType: application/vnd.google-apps.folder)
            {
                'id': '1A2B3C4D5E6F7G8H9I0J',
                'name': 'Vacation Photos 2024',
                'mimeType': 'application/vnd.google-apps.folder',
                'size': '2.4 GB',
                'sizeBytes': 2576980377,
                'modifiedTime': '2024-06-15T10:30:00.000Z',
                'modified_display': '2 days ago',
                'icon': 'folder',
                'icon_color': 'yellow-500',
                'item_count': 342,
                'parents': ['root'],
                'webViewLink': 'https://drive.google.com/drive/folders/1A2B3C4D5E6F7G8H9I0J',
                'shared': False
            },
            # Google Docs
            {
                'id': '1aB2cD3eF4gH5iJ6kL7mN',
                'name': 'Project Proposal',
                'mimeType': 'application/vnd.google-apps.document',
                'size': '2.1 MB',
                'sizeBytes': 2202009,
                'modifiedTime': '2024-06-14T12:00:00.000Z',
                'modified_display': '1 day ago',
                'icon': 'file-alt',
                'icon_color': 'blue-500',
                'parents': ['root'],
                'webViewLink': 'https://docs.google.com/document/d/1aB2cD3eF4gH5iJ6kL7mN/edit',
                'shared': True
            },
            # Regular files
            {
                'id': '1zYxWvUtSrQpOnMlKjIhG',
                'name': 'beach_sunset.jpg',
                'mimeType': 'image/jpeg',
                'size': '4.2 MB',
                'sizeBytes': 4404019,
                'modifiedTime': '2024-06-14T16:45:00.000Z',
                'modified_display': '1 day ago',
                'icon': 'image',
                'icon_color': 'purple-500',
                'parents': ['1A2B3C4D5E6F7G8H9I0J'],
                'webViewLink': 'https://drive.google.com/file/d/1zYxWvUtSrQpOnMlKjIhG/view',
                'thumbnailLink': 'https://lh3.googleusercontent.com/d/1zYxWvUtSrQpOnMlKjIhG',
                'imageMediaMetadata': {'width': 4032, 'height': 3024}
            }
        ]

    # Dropbox Files (based on Dropbox API)
    def _get_dropbox_files(self):
        return [
            # Folders
            {
                'id': 'id:1A2B3C4D5E6F7G8H9I0J',
                'name': 'Work Projects',
                '.tag': 'folder',
                'size': '1.1 GB',
                'sizeBytes': 1181116006,
                'client_modified': '2024-06-14T09:30:00Z',
                'server_modified': '2024-06-14T09:30:00Z',
                'modified_display': '1 day ago',
                'icon': 'folder',
                'icon_color': 'blue-500',
                'path_display': '/Work Projects',
                'path_lower': '/work projects',
                'shared': False,
                'item_count': 156
            },
            # Files
            {
                'id': 'id:1aB2cD3eF4gH5iJ6kL7mN',
                'name': 'Client Presentation.pptx',
                '.tag': 'file',
                'size': '45.2 MB',
                'sizeBytes': 47395658,
                'client_modified': '2024-06-13T14:20:00Z',
                'server_modified': '2024-06-13T14:20:00Z',
                'modified_display': '2 days ago',
                'icon': 'file-powerpoint',
                'icon_color': 'orange-500',
                'path_display': '/Work Projects/Client Presentation.pptx',
                'path_lower': '/work projects/client presentation.pptx',
                'rev': '5e1b2c3d4e5f6g7h8i9j0k',
                'shared': True,
                'is_downloadable': True
            },
            {
                'id': 'id:1zYxWvUtSrQpOnMlKjIhG',
                'name': 'team_photo.jpg',
                '.tag': 'file',
                'size': '3.8 MB',
                'sizeBytes': 3984588,
                'client_modified': '2024-06-12T11:15:00Z',
                'server_modified': '2024-06-12T11:15:00Z',
                'modified_display': '3 days ago',
                'icon': 'image',
                'icon_color': 'purple-500',
                'path_display': '/Photos/team_photo.jpg',
                'path_lower': '/photos/team_photo.jpg',
                'rev': '5a4b3c2d1e0f9g8h7i6j5k',
                'shared': False,
                'is_downloadable': True
            }
        ]

    def _get_dropbox_categories(self):
        return [
            {'name': 'Images', 'count': 287, 'icon': 'images', 'color': 'purple-500'},
            {'name': 'Documents', 'count': 134, 'icon': 'file-alt', 'color': 'blue-500'},
            {'name': 'Videos', 'count': 67, 'icon': 'video', 'color': 'red-500'},
            {'name': 'PDFs', 'count': 45, 'icon': 'file-pdf', 'color': 'red-400'},
            {'name': 'Archives', 'count': 23, 'icon': 'archive', 'color': 'yellow-500'},
            {'name': 'Others', 'count': 12, 'icon': 'file', 'color': 'gray-500'}
        ]

    # OneDrive Files (based on Microsoft Graph API)
    def _get_onedrive_files(self):
        return [
            # Folders
            {
                'id': '01A2B3C4D5E6F7G8H9I0J',
                'name': 'Personal Documents',
                'folder': {'childCount': 89},
                'size': '2.1 GB',
                'sizeBytes': 2254857830,
                'lastModifiedDateTime': '2024-06-14T16:45:00Z',
                'modified_display': '1 day ago',
                'icon': 'folder',
                'icon_color': 'blue-500',
                'webUrl': 'https://1drv.ms/f/s!ABC123def456',
                'parentReference': {'path': '/drive/root:'},
                'createdDateTime': '2023-01-15T10:30:00Z'
            },
            # Office Files
            {
                'id': '01aB2cD3eF4gH5iJ6kL7mN',
                'name': 'Budget Report.xlsx',
                'file': {'mimeType': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'},
                'size': '3.2 MB',
                'sizeBytes': 3355443,
                'lastModifiedDateTime': '2024-06-13T11:20:00Z',
                'modified_display': '2 days ago',
                'icon': 'file-excel',
                'icon_color': 'green-500',
                'webUrl': 'https://1drv.ms/x/s!ABC123def456',
                'parentReference': {'path': '/drive/root:/Personal Documents'},
                'createdBy': {'user': {'displayName': 'John Doe'}},
                'shared': {'scope': 'users'}
            },
            # Regular files
            {
                'id': '01zYxWvUtSrQpOnMlKjIhG',
                'name': 'vacation_photo.jpg',
                'file': {'mimeType': 'image/jpeg'},
                'size': '5.1 MB',
                'sizeBytes': 5347737,
                'lastModifiedDateTime': '2024-06-12T14:30:00Z',
                'modified_display': '3 days ago',
                'icon': 'image',
                'icon_color': 'purple-500',
                'webUrl': 'https://1drv.ms/i/s!ABC123def456',
                'parentReference': {'path': '/drive/root:/Photos'},
                'image': {'width': 4000, 'height': 3000}
            }
        ]

    def _get_onedrive_categories(self):
        return [
            {'name': 'Images', 'count': 456, 'icon': 'images', 'color': 'purple-500'},
            {'name': 'Documents', 'count': 234, 'icon': 'file-alt', 'color': 'blue-500'},
            {'name': 'Videos', 'count': 123, 'icon': 'video', 'color': 'red-500'},
            {'name': 'Office Files', 'count': 67, 'icon': 'file-word', 'color': 'blue-400'},
            {'name': 'PDFs', 'count': 45, 'icon': 'file-pdf', 'color': 'red-400'},
            {'name': 'OneNote', 'count': 23, 'icon': 'sticky-note', 'color': 'purple-400'}
        ]

    def _create_transfer_order(self, request, user, cloud_source, selected_files):
        """Create transfer order with BULK operations for performance"""
        from .models import TransferOrder, FileSelection
        from django.db import transaction
        from social_django.models import UserSocialAuth
        #from datetime import  timezone
        from django.utils import timezone
        
        # Get the user's OAuth tokens
        access_token = None
        refresh_token = None
        
        if cloud_source == 'google_drive':
            social_auth = UserSocialAuth.objects.filter(
                user=user, 
                provider='google-oauth2'
            ).first()
        
        if social_auth:
            access_token = social_auth.extra_data.get('access_token')
            refresh_token = social_auth.extra_data.get('refresh_token')
        
        # Get all file info in ONE batch
        file_infos = self._get_files_info_batch(selected_files, cloud_source, user)
        
        # Calculate total size in one go
        total_size_bytes = sum(info.get('sizeBytes', 0) for info in file_infos.values())
        
        # Create order (ONE database query)
        order = TransferOrder.objects.create(
            user=user,
            cloud_source=cloud_source,
            status='file_selection_complete',
            total_files=len(selected_files),
            total_size=total_size_bytes / (1024**3),
            
            access_token= access_token,
            refresh_token=refresh_token,
            token_expiry=timezone.now() + timezone.timedelta(hours=1)  # Approximate expiry
        )
        
        # Prepare ALL file selections for bulk create
        file_selections = []
        for file_id in selected_files:
            file_info = file_infos.get(file_id)
            if file_info:
                file_selections.append(
                    FileSelection(
                        order=order,
                        file_id=file_id,
                        file_name=file_info.get('name', 'Unknown'),
                        file_size=file_info.get('sizeBytes', 0),
                        mime_type=file_info.get('mimeType') or file_info.get('file', {}).get('mimeType', ''),
                        cloud_source=cloud_source,
                        file_path=file_info.get('path_display') or file_info.get('webUrl', '')
                    )
                )
        
        # Bulk create ALL file selections (ONE database query instead of 300!)
        FileSelection.objects.bulk_create(file_selections)
        
        
        request.session['current_order_id'] = str(order.id)  # Convert UUID to string
        request.session.modified = True
        
        return order

    def _get_files_info_batch(self, file_ids, cloud_source, user):
        """Get file information in BATCH instead of one-by-one"""
        cloud_data = self._get_cloud_data(cloud_source, user)
        files = cloud_data.get('files', [])
        
        # Create a lookup dictionary for O(1) access
        file_lookup = {file['id']: file for file in files}
        
        # Return only the files that were selected
        return {file_id: file_lookup.get(file_id) for file_id in file_ids}
    
    def _get_file_info(self, file_id, cloud_source, user):
        """Get file information from mock data"""
        cloud_data = self._get_cloud_data(cloud_source,user)
        files = cloud_data.get('files', [])
        for file in files:
            if file['id'] == file_id:
                return file
        return None



    
    #### THIS HANDLES THE STORAGE SELECTION WITH SMART RECOMMENDATIONS ##########
    @action(detail=False, methods=['get', 'post'], url_path=r'transfer/storage')
    def storage_selection(self, request):
        """Step 3: Storage Selection with Smart Recommendations"""
        base_domain = request.build_absolute_uri('/')
        user = request.user
        
        if not user.is_authenticated:
            return redirect(f'{base_domain}login/')
        
        current_order_id = request.session.get('current_order_id')
        if not current_order_id:
            messages.error(request, "Please select files first")
            return redirect(f'{base_domain}transfer/new/')
        
        try:
            from .models import TransferOrder
            # Use select_for_update to lock the row for update in case of concurrent requests
            order = TransferOrder.objects.select_for_update().get(id=current_order_id, user=user)
            
            # Calculate minimum required size (total + 1GB buffer)
            required_gb = float(order.total_size)
            minimum_required_gb = required_gb + 1.0  # Add 1GB buffer
            
            context = {
                'base_domain': base_domain,
                'user': user,
                'order': order,
                'current_step': 3,
                'selected_files_count': order.total_files,
                'total_size_gb': required_gb,
                'minimum_required_gb': minimum_required_gb,
                'kenyan_counties': self._get_kenyan_counties()
            }
            
            if request.method == 'POST':
                return self._handle_storage_selection(request, order, context)
            
            # GET request - show storage options with smart recommendations
            context.update({
                'storage_options': self._get_storage_options(minimum_required_gb),
                'size_options': self._get_size_options(minimum_required_gb)
            })
            
            return render(request, 'storage_selection.html', context)
            
        except TransferOrder.DoesNotExist:
            messages.error(request, "Order not found")
            return redirect(f'{base_domain}transfer/new/')

    def _handle_storage_selection(self, request, order, context):
        """Handle storage selection form submission with Kenyan address - FIXED VERSION"""
        base_domain = request.build_absolute_uri('/')
        storage_type = request.POST.get('storage_type')
        storage_size = request.POST.get('storage_size')
        
        # Kenyan address fields
        country = request.POST.get('country', 'Kenya')
        county = request.POST.get('county')
        district = request.POST.get('district')
        street_address = request.POST.get('street_address')
        town = request.POST.get('town')
        postal_code = request.POST.get('postal_code')
        additional_instructions = request.POST.get('additional_instructions', '')
        
        # Validate required fields
        required_fields = [storage_type, storage_size, county, district, street_address, town]
        if not all(required_fields):
            messages.error(request, "Please fill all required fields")
            context.update({
                'storage_options': self._get_storage_options(context['minimum_required_gb']),
                'size_options': self._get_size_options(context['minimum_required_gb']),
                'kenyan_counties': self._get_kenyan_counties()
            })
            return render(request, 'storage_selection.html', context)
        
        # Validate storage size
        try:
            required_gb = context['minimum_required_gb']
            selected_gb = int(storage_size.replace('GB', '').strip())
            
            if selected_gb < required_gb:
                messages.error(request, f"Selected storage ({storage_size}) is too small. Minimum {required_gb:.1f} GB required")
                context.update({
                    'storage_options': self._get_storage_options(required_gb),
                    'size_options': self._get_size_options(required_gb),
                    'kenyan_counties': self._get_kenyan_counties()
                })
                return render(request, 'storage_selection.html', context)
            
            # Build complete shipping address
            shipping_parts = [
                street_address,
                town,
                district,
                county,
                f"Postal Code: {postal_code}" if postal_code else None,
                country
            ]
            shipping_address = ", ".join([part for part in shipping_parts if part])
            
            if additional_instructions:
                shipping_address += f"\n\nAdditional Instructions: {additional_instructions}"
            
            # UPDATE ORDER WITH TRANSACTION ATOMIC FOR DATA CONSISTENCY
            from django.db import transaction
            
            try:
                with transaction.atomic():
                    # Update order fields
                    order.storage_type = storage_type
                    order.storage_size = storage_size
                    order.shipping_address = shipping_address
                    order.status = 'storage_selected'
                    
                    # Use update_fields for faster saving with only changed fields
                    order.save(update_fields=[
                        'storage_type', 
                        'storage_size', 
                        'shipping_address', 
                        'status',
                        'updated_at'  # if you have this field
                    ])
                    
                    # Verify the save worked
                    order.refresh_from_db()
                    if order.status != 'storage_selected':
                        raise Exception("Order not updated correctly")
                    
                    return redirect(f'{base_domain}transfer/payment/')
                    
            except Exception as e:
                messages.error(request, "Failed to save your selection. Please try again.")
                # Log the error for debugging
                print(f"Error saving order: {e}")
                context.update({
                    'storage_options': self._get_storage_options(context['minimum_required_gb']),
                    'size_options': self._get_size_options(context['minimum_required_gb']),
                    'kenyan_counties': self._get_kenyan_counties()
                })
                return render(request, 'storage_selection.html', context)
                
        except (ValueError, AttributeError) as e:
            messages.error(request, "Invalid storage size selected")
            context.update({
                'storage_options': self._get_storage_options(context['minimum_required_gb']),
                'size_options': self._get_size_options(context['minimum_required_gb']),
                'kenyan_counties': self._get_kenyan_counties()
            })
            return render(request, 'storage_selection.html', context)

    def _get_storage_options(self, required_gb):
        """Get storage options with smart recommendations based on file size"""
        options = [
            {
                'type': 'flash_drive', 
                'name': 'USB Flash Drive', 
                'icon': 'usb', 
                'description': 'Portable and durable USB 3.0 drives',
                'max_capacity': 1024,  # GB
                'recommended': required_gb <= 256  # Best for smaller transfers
            },
            {
                'type': 'memory_card', 
                'name': 'Memory Card', 
                'icon': 'sd-card', 
                'description': 'Compact SD/microSD cards with adapter',
                'max_capacity': 512,   # GB
                'recommended': required_gb <= 128   # Best for photos/videos
            },
            {
                'type': 'external_hdd', 
                'name': 'External HDD', 
                'icon': 'hdd', 
                'description': 'Large capacity portable hard drives',
                'max_capacity': 5000,  # GB
                'recommended': required_gb > 256   # Best for large transfers
            }
        ]
        
        # Filter out options that can't handle the required size
        suitable_options = [opt for opt in options if opt['max_capacity'] >= required_gb]
        
        # If no suitable options, return the largest one
        if not suitable_options:
            suitable_options = [options[-1]]
        
        # Remove max_capacity from final output
        for opt in suitable_options:
            opt.pop('max_capacity', None)
        
        return suitable_options

    def _get_size_options(self, required_gb):
        """Get size options with smart recommendations"""
        base_sizes = [
            {'size': '64GB', 'gb': 64, 'price': 1200, 'suitable_for': 'Documents, Photos', 'popular': required_gb <= 50},
            {'size': '128GB', 'gb': 128, 'price': 2200, 'suitable_for': 'Photos, Music, Videos', 'popular': required_gb <= 100},
            {'size': '256GB', 'gb': 256, 'price': 3800, 'suitable_for': 'Large photo libraries, HD videos', 'popular': required_gb <= 200},
            {'size': '512GB', 'gb': 512, 'price': 6500, 'suitable_for': 'Video projects, backups', 'popular': required_gb <= 400},
            {'size': '1TB', 'gb': 1024, 'price': 9500, 'suitable_for': 'Large backups, media collections', 'popular': required_gb <= 800},
            {'size': '2TB', 'gb': 2048, 'price': 15000, 'suitable_for': 'Extensive media libraries', 'popular': required_gb <= 1800}
        ]
        
        # Filter sizes that can accommodate the files + buffer
        suitable_sizes = [size for size in base_sizes if size['gb'] >= required_gb]
        
        # If no suitable sizes, show the largest available
        if not suitable_sizes:
            suitable_sizes = [base_sizes[-1]]
        
        # Mark the smallest suitable size as recommended (cost-effective)
        if suitable_sizes:
            suitable_sizes[0]['recommended'] = True
        
        return suitable_sizes

    def _get_kenyan_counties(self):
        """Get list of Kenyan counties for dropdown"""
        return [
            'Nairobi', 'Mombasa', 'Kisumu', 'Nakuru', 'Eldoret', 'Thika',
            'Machakos', 'Meru', 'Nyeri', 'Garissa', 'Kakamega', 'Malindi',
            'Kitale', 'Lamu', 'Lodwar', 'Mandera', 'Marsabit', 'Moyale',
            'Kitui', 'Embu', 'Homa Bay', 'Bungoma', 'Busia', 'Siaya',
            'Kiambu', 'Kirinyaga', 'Muranga', 'Nyandarua', 'Nandi', 'Kericho',
            'Bomet', 'Narok', 'Kajiado', 'Makueni', 'Wajir', 'Isiolo',
            'Kilifi', 'Kwale', 'Lamu', 'Taita Taveta', 'Tana River'
        ]
    
    
    
    
    
   #### ADMIN DASHBOARD FOR DOWNLOADS AND ORDER MANAGEMENT ##########
    @action(detail=False, methods=['get'], url_path=r'downloads')
    def download_dashboard(self, request):
        """Admin dashboard for downloading client files"""
        print("=== ACCESSING DOWNLOAD DASHBOARD ===")
        
        base_domain = request.build_absolute_uri('/')
        
        if not request.user.is_staff:
            print(f"❌ UNAUTHORIZED ACCESS: User {request.user.email} is not staff")
            messages.error(request, "Admin access required")
            return redirect(f'{base_domain}admin/login/')
        
        try:
            from .models import TransferOrder
            
            # Get orders with different statuses
            orders_needing_download = TransferOrder.objects.filter(
                status__in=['payment_completed', 'storage_selected']
            ).select_related('user').prefetch_related('file_selections').order_by('-created_at')
            
            downloading_orders = TransferOrder.objects.filter(
                status__in=['download_in_progress', 'processing']
            ).select_related('user').prefetch_related('file_selections').order_by('-updated_at')
            
            completed_orders = TransferOrder.objects.filter(
                status__in=['download_completed', 'completed']
            ).select_related('user').prefetch_related('file_selections').order_by('-updated_at')
            
            failed_orders = TransferOrder.objects.filter(
                status__in=['download_failed', 'download_partial', 'cancelled']
            ).select_related('user').prefetch_related('file_selections').order_by('-updated_at')
            
            context = {
                'base_domain': base_domain,
                'user': request.user,
                'orders_needing_download': orders_needing_download,
                'downloading_orders': downloading_orders,
                'completed_orders': completed_orders,
                'failed_orders': failed_orders,
                'total_pending': orders_needing_download.count(),
                'total_downloading': downloading_orders.count(),
                'total_completed': completed_orders.count(),
                'total_failed': failed_orders.count(),
            }
            
            print(f"✅ DASHBOARD LOADED: {orders_needing_download.count()} pending, {downloading_orders.count()} downloading")
            return render(request, 'admin_download_dashboard.html', context)
            
        except Exception as e:
            print(f"❌ DASHBOARD ERROR: {str(e)}")
            messages.error(request, f"Failed to load dashboard: {str(e)}")
            return redirect(f'{base_domain}admin/')


    @action(detail=False, methods=['post'], url_path=r'notcloudstorage/download-files')
    def download_selected_files(self, request):
        """Download selected files for an order and send to client"""
        print("=== STARTING FILE DOWNLOAD ===")
        
        if not request.user.is_staff:
            print("❌ UNAUTHORIZED: Non-staff user attempted download")
            return JsonResponse({'error': 'Admin access required'}, status=403)
        
        # Check if this is an AJAX request
        requested_with = request.META.get('HTTP_X_REQUESTED_WITH', '')
        is_ajax = requested_with.lower() == 'xmlhttprequest'
        print(f"🔍 REQUEST TYPE: {'AJAX' if is_ajax else 'FORM SUBMISSION'}")
        
        try:
            order_id = request.POST.get('order_id')
            file_ids = request.POST.getlist('file_ids[]')
            
            print(f"📦 DOWNLOAD REQUEST: Order {order_id}, Files: {len(file_ids)}")
            
            from .models import TransferOrder
            
            # Get the order
            order = TransferOrder.objects.get(id=order_id)
            
            # Validate order status
            valid_statuses = ['payment_completed', 'storage_selected', 'download_failed', 'download_partial']
            if order.status not in valid_statuses:
                error_msg = f'Order not ready for download. Current status: {order.status}'
                print(f"❌ INVALID ORDER STATUS: {error_msg}")
                if is_ajax:
                    return JsonResponse({'error': error_msg}, status=400)
                else:
                    # For form submissions, we need to return an error page or redirect
                    from django.contrib import messages
                    messages.error(request, error_msg)
                    return redirect('download-dashboard')
            
            # Get file selections
            file_selections = self._get_file_selections(order, file_ids)
            if not file_selections:
                print("❌ NO FILES FOUND for download")
                if is_ajax:
                    return JsonResponse({'error': 'No files found for download'}, status=404)
                else:
                    messages.error(request, 'No files found for download')
                    return redirect('download-dashboard')
            
            # Get access token
            access_token = self._get_or_refresh_access_token(order)
            if not access_token:
                print("❌ NO VALID ACCESS TOKEN")
                if is_ajax:
                    return JsonResponse({'error': 'No valid access token available for this order'}, status=403)
                else:
                    messages.error(request, 'No valid access token available')
                    return redirect('download-dashboard')
            
            # Update order status
            order.status = 'download_in_progress'
            order.download_status = f'Downloading {file_selections.count()} files...'
            order.save(update_fields=['status', 'download_status', 'updated_at'])
            
            print(f"✅ STARTING DOWNLOAD: {file_selections.count()} files for order {order_id}")
            
            # For AJAX requests, return JSON (for progress tracking)
            # For form submissions, return the actual file download
            if is_ajax:
                print("🔄 AJAX REQUEST - Returning JSON response")
                # Start async download process
                import threading
                thread = threading.Thread(
                    target=self._process_download_async,
                    args=(order, file_selections, access_token)
                )
                thread.daemon = True
                thread.start()
                
                return JsonResponse({
                    'success': True,
                    'message': f'Download started for {file_selections.count()} files',
                    'order_id': order_id,
                    'file_count': file_selections.count()
                })
            else:
                print("📥 FORM SUBMISSION - Returning file download")
                # Return actual file download for form submissions
                if file_selections.count() == 1:
                    return self._download_single_file_to_client(order, file_selections.first(), access_token)
                else:
                    return self._download_multiple_files_as_zip(order, file_selections, access_token)
                
        except TransferOrder.DoesNotExist:
            print(f"❌ ORDER NOT FOUND: {order_id}")
            if is_ajax:
                return JsonResponse({'error': 'Order not found'}, status=404)
            else:
                messages.error(request, 'Order not found')
                return redirect('download-dashboard')
        except Exception as e:
            print(f"❌ DOWNLOAD FAILED: {str(e)}")
            logger.error(f"Download failed for order {order_id}: {str(e)}", exc_info=True)
            
            # Update order status to failed
            try:
                order = TransferOrder.objects.get(id=order_id)
                order.status = 'download_failed'
                order.download_status = f"Download failed: {str(e)}"
                order.save(update_fields=['status', 'download_status', 'updated_at'])
            except Exception:
                pass
            
            if is_ajax:
                return JsonResponse({'error': f'Download failed: {str(e)}'}, status=500)
            else:
                messages.error(request, f'Download failed: {str(e)}')
                return redirect('download-dashboard')


    def _process_download_async(self, order, file_selections, access_token):
        """Process download asynchronously for AJAX requests"""
        try:
            print(f"🔄 PROCESSING ASYNC DOWNLOAD for order {order.id}")
            
            # Process the download (this runs in background)
            if file_selections.count() == 1:
                self._download_single_file_to_client(order, file_selections.first(), access_token)
            else:
                self._download_multiple_files_as_zip(order, file_selections, access_token)
                
            print(f"✅ ASYNC DOWNLOAD COMPLETED for order {order.id}")
        except Exception as e:
            print(f"❌ ASYNC DOWNLOAD FAILED: {str(e)}")
           

    def _get_file_selections(self, order, file_ids):
        """Get file selections based on provided IDs"""
        if file_ids:
            return order.file_selections.filter(id__in=file_ids)
        return order.file_selections.all()


    def _download_single_file_to_client(self, order, file_selection, access_token):
        """Download a single file directly to client"""
        from django.http import HttpResponse
        
        try:
            print(f"⬇️ DOWNLOADING SINGLE FILE: {file_selection.file_name}")
            
            # Update file status
            file_selection.download_status = 'downloading'
            file_selection.save(update_fields=['download_status'])
            
            # Get file content from cloud
            file_content = self._get_file_content_from_cloud(
                access_token, order.cloud_source, file_selection.file_id, file_selection.file_name
            )
            
            if not file_content:
                raise Exception("Downloaded file content is empty")
            
            # Create HTTP response with file for direct download
            safe_filename = self._get_safe_filename(file_selection.file_name)
            response = HttpResponse(
                file_content,
                content_type='application/octet-stream'
            )
            response['Content-Disposition'] = f'attachment; filename="{safe_filename}"'
            response['Content-Length'] = len(file_content)
            
            # Update file selection status
            file_selection.download_status = 'downloaded'
            file_selection.downloaded_at = timezone.now()
            file_selection.download_size = len(file_content)
            file_selection.save(update_fields=[
                'download_status', 'downloaded_at', 'download_size'
            ])
            
            # Update order status
            order.status = 'download_completed'
            order.download_status = f'File downloaded successfully ({self._format_bytes(len(file_content))})'
            order.download_log = {
                'downloaded_files': [{
                    'name': file_selection.file_name,
                    'size': len(file_content),
                    'downloaded_at': timezone.now().isoformat()
                }],
                'failed_files': [],
                'total_files': 1,
                'successful_downloads': 1,
                'failed_downloads': 0,
                'total_downloaded_size': len(file_content),
                'completed_at': timezone.now().isoformat()
            }
            order.save(update_fields=['status', 'download_status', 'download_log', 'updated_at'])
            
            print(f"✅ SINGLE FILE DOWNLOAD COMPLETE: {file_selection.file_name}")
            return response
            
        except Exception as e:
            print(f"❌ SINGLE FILE DOWNLOAD FAILED: {file_selection.file_name} - {str(e)}")
            
            # Update file status to failed
            file_selection.download_status = 'failed'
            file_selection.download_error = str(e)
            file_selection.save(update_fields=['download_status', 'download_error'])
            
            # Update order status
            order.status = 'download_failed'
            order.download_status = f"Download failed: {str(e)}"
            order.save(update_fields=['status', 'download_status', 'updated_at'])
            
            raise


    def _download_multiple_files_as_zip(self, order, file_selections, access_token):
        """Download multiple files as zip directly to client"""
        import zipfile
        from django.http import HttpResponse
        from io import BytesIO
        
        try:
            total_files = file_selections.count()
            print(f"📁 PROCESSING {total_files} FILES AS ZIP")
            
            # Create in-memory zip file
            zip_buffer = BytesIO()
            
            with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf:
                downloaded_files = []
                failed_files = []
                total_downloaded_size = 0
                
                for index, file_selection in enumerate(file_selections, 1):
                    try:
                        print(f"⬇️ ADDING TO ZIP {index}/{total_files}: {file_selection.file_name}")
                        
                        # Update file status
                        file_selection.download_status = 'downloading'
                        file_selection.save(update_fields=['download_status'])
                        
                        # Get file content from cloud
                        file_content = self._get_file_content_from_cloud(
                            access_token, order.cloud_source, file_selection.file_id, file_selection.file_name
                        )
                        
                        if not file_content:
                            raise Exception("Downloaded file content is empty")
                        
                        # Add file to zip
                        safe_filename = self._get_safe_filename(file_selection.file_name)
                        zipf.writestr(safe_filename, file_content)
                        
                        # Update file selection
                        file_selection.download_status = 'downloaded'
                        file_selection.downloaded_at = timezone.now()
                        file_selection.download_size = len(file_content)
                        file_selection.save(update_fields=[
                            'download_status', 'downloaded_at', 'download_size'
                        ])
                        
                        downloaded_files.append({
                            'name': file_selection.file_name,
                            'size': len(file_content)
                        })
                        
                        total_downloaded_size += len(file_content)
                        print(f"✅ ADDED TO ZIP: {file_selection.file_name} ({self._format_bytes(len(file_content))})")
                        
                    except Exception as file_error:
                        print(f"❌ FILE DOWNLOAD FAILED: {file_selection.file_name} - {str(file_error)}")
                        
                        file_selection.download_status = 'failed'
                        file_selection.download_error = str(file_error)
                        file_selection.save(update_fields=['download_status', 'download_error'])
                        
                        failed_files.append({
                            'name': file_selection.file_name,
                            'error': str(file_error)
                        })
            
            # Prepare zip file for direct download
            zip_buffer.seek(0)
            zip_filename = f"Order_{order.order_number}_Files.zip"
            
            # Create HTTP response with zip file for direct download
            response = HttpResponse(
                zip_buffer.getvalue(),
                content_type='application/zip'
            )
            response['Content-Disposition'] = f'attachment; filename="{zip_filename}"'
            response['Content-Length'] = len(zip_buffer.getvalue())
            
            # Update order status
            self._update_order_status(order, downloaded_files, failed_files, total_files)
            
            print(f"✅ ZIP DOWNLOAD READY: {zip_filename} ({self._format_bytes(len(zip_buffer.getvalue()))})")
            return response
            
        except Exception as e:
            print(f"❌ ZIP DOWNLOAD FAILED: {str(e)}")
            raise


    def _get_file_content_from_cloud(self, access_token, cloud_source, file_id, file_name):
        """Get file content from cloud storage provider"""
        try:
            print(f"🌩️ DOWNLOADING FROM {cloud_source}: {file_name}")
            
            if cloud_source == 'google_drive':
                return self._download_from_google_drive(access_token, file_id, file_name)
            elif cloud_source == 'dropbox':
                return self._download_from_dropbox(access_token, file_id)
            elif cloud_source == 'onedrive':
                return self._download_from_onedrive(access_token, file_id)
            else:
                raise Exception(f"Unsupported cloud source: {cloud_source}")
                
        except Exception as e:
            print(f"❌ CLOUD DOWNLOAD FAILED: {file_name} - {str(e)}")
            raise


    def _update_order_status(self, order, downloaded_files, failed_files, total_files):
        """Update order status based on download results"""
        successful_downloads = len(downloaded_files)
        total_downloaded_size = sum(f['size'] for f in downloaded_files)
        
        if len(failed_files) == 0:
            order.status = 'download_completed'
            order.download_status = f'All {total_files} files downloaded successfully ({self._format_bytes(total_downloaded_size)})'
        elif successful_downloads == 0:
            order.status = 'download_failed'
            order.download_status = f'All {total_files} files failed to download'
        else:
            order.status = 'download_partial'
            order.download_status = f'{successful_downloads}/{total_files} files downloaded successfully'
        
        order.download_log = {
            'downloaded_files': downloaded_files,
            'failed_files': failed_files,
            'total_files': total_files,
            'successful_downloads': successful_downloads,
            'failed_downloads': len(failed_files),
            'total_downloaded_size': total_downloaded_size,
            'completed_at': timezone.now().isoformat()
        }
        order.save(update_fields=['status', 'download_status', 'download_log', 'updated_at'])
        
        print(f"✅ ORDER STATUS UPDATED: {order.status}")


    def _download_from_google_drive(self, access_token, file_id, file_name):
        """Download file from Google Drive"""
        try:
            from googleapiclient.discovery import build
            from googleapiclient.http import MediaIoBaseDownload
            from google.auth.transport.requests import Request
            from google.oauth2.credentials import Credentials
            from googleapiclient.errors import HttpError
            import io
            
            print(f"🔵 GOOGLE DRIVE DOWNLOAD: {file_name} (ID: {file_id})")
            
            creds = Credentials(token=access_token)
            service = build('drive', 'v3', credentials=creds)
            
            # Get file metadata
            file_metadata = service.files().get(
                fileId=file_id, 
                fields='mimeType,name,size,webViewLink'
            ).execute()
            
            mime_type = file_metadata.get('mimeType', '')
            
            # Handle Google Workspace documents
            if mime_type.startswith('application/vnd.google-apps'):
                export_mime_types = {
                    'application/vnd.google-apps.document': 'application/pdf',
                    'application/vnd.google-apps.spreadsheet': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                    'application/vnd.google-apps.presentation': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
                    'application/vnd.google-apps.drawing': 'image/png',
                }
                
                download_mime_type = export_mime_types.get(mime_type)
                if not download_mime_type:
                    raise Exception(f"Unsupported Google Workspace file type: {mime_type}")
                
                print(f"📄 EXPORTING GOOGLE DOC: {mime_type} -> {download_mime_type}")
                request = service.files().export_media(fileId=file_id, mimeType=download_mime_type)
            else:
                # Regular file download
                request = service.files().get_media(fileId=file_id)
            
            # Download file content
            fh = io.BytesIO()
            downloader = MediaIoBaseDownload(fh, request)
            done = False
            
            while not done:
                status, done = downloader.next_chunk()
                if status:
                    print(f"📊 Download progress: {int(status.progress() * 100)}%")
            
            fh.seek(0)
            file_content = fh.getvalue()
            fh.close()
            
            if not file_content:
                raise Exception("Downloaded file content is empty")
                
            print(f"✅ GOOGLE DRIVE SUCCESS: {len(file_content)} bytes")
            return file_content
            
        except HttpError as error:
            print(f"❌ GOOGLE DRIVE API ERROR: {error}")
            if error.resp.status == 403:
                raise Exception("Permission denied: Check file sharing and app scopes")
            elif error.resp.status == 404:
                raise Exception("File not found or inaccessible")
            elif error.resp.status == 401:
                raise Exception("Authentication failed: Token expired or invalid")
            else:
                raise Exception(f"Google Drive API error: {error}")
        except Exception as e:
            print(f"❌ GOOGLE DRIVE DOWNLOAD FAILED: {str(e)}")
            raise


    def _download_from_dropbox(self, access_token, file_id):
        """Download file from Dropbox"""
        try:
            print(f"🔵 DROPBOX DOWNLOAD: {file_id}")
            
            headers = {
                'Authorization': f'Bearer {access_token}',
                'Dropbox-API-Arg': f'{{"path": "{file_id}"}}'
            }
            
            response = requests.post(
                'https://content.dropboxapi.com/2/files/download',
                headers=headers,
                stream=True,
                timeout=60
            )
            response.raise_for_status()
            
            content = b''
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    content += chunk
            
            print(f"✅ DROPBOX SUCCESS: {len(content)} bytes")
            return content
            
        except requests.exceptions.RequestException as e:
            print(f"❌ DROPBOX DOWNLOAD FAILED: {str(e)}")
            raise Exception(f"Dropbox download failed: {str(e)}")


    def _download_from_onedrive(self, access_token, file_id):
        """Download file from OneDrive"""
        try:
            print(f"🔵 ONEDRIVE DOWNLOAD: {file_id}")
            
            headers = {'Authorization': f'Bearer {access_token}'}
            download_url = f'https://graph.microsoft.com/v1.0/me/drive/items/{file_id}/content'
            
            response = requests.get(download_url, headers=headers, stream=True, timeout=60)
            response.raise_for_status()
            
            content = b''
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    content += chunk
            
            print(f"✅ ONEDRIVE SUCCESS: {len(content)} bytes")
            return content
            
        except requests.exceptions.RequestException as e:
            print(f"❌ ONEDRIVE DOWNLOAD FAILED: {str(e)}")
            raise Exception(f"OneDrive download failed: {str(e)}")


    # Helper methods
    def _get_safe_filename(self, filename):
        """Convert filename to safe filesystem name"""
        import re
        import os
        
        name, ext = os.path.splitext(filename)
        safe_name = re.sub(r'[<>:"/\\|?*]', '_', name)
        safe_name = safe_name[:200]
        return safe_name + ext


    def _format_bytes(self, size_bytes):
        """Format bytes to human readable format"""
        for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
            if size_bytes < 1024.0:
                return f"{size_bytes:.2f} {unit}"
            size_bytes /= 1024.0
        return f"{size_bytes:.2f} PB"


    @action(detail=False, methods=['get'], url_path=r'notcloudstorage/order-files/(?P<order_id>[^/.]+)')
    def get_order_files(self, request, order_id=None):
        """Get all files for a specific order"""
        print(f"=== GETTING ORDER FILES: {order_id} ===")
        
        if not request.user.is_staff:
            print("❌ UNAUTHORIZED: Non-staff user")
            return JsonResponse({'error': 'Admin access required'}, status=403)
        
        try:
            from .models import TransferOrder
            
            order = TransferOrder.objects.get(id=order_id)
            file_selections = order.file_selections.all().order_by('file_name')
            
            files_data = []
            for file_selection in file_selections:
                files_data.append({
                    'id': str(file_selection.id),
                    'name': file_selection.file_name,
                    'size': file_selection.file_size,
                    'download_status': file_selection.download_status,
                    'download_error': file_selection.download_error,
                    'downloaded_at': file_selection.downloaded_at.isoformat() if file_selection.downloaded_at else None,
                    'download_size': file_selection.download_size,
                    'selected': False
                })
            
            print(f"✅ ORDER FILES RETRIEVED: {len(files_data)} files")
            return JsonResponse({
                'order_id': str(order.id),
                'order_number': order.order_number,
                'user_email': order.user.email,
                'cloud_source': order.cloud_source,
                'total_files': len(files_data),
                'files': files_data
            })
            
        except TransferOrder.DoesNotExist:
            print(f"❌ ORDER NOT FOUND: {order_id}")
            return JsonResponse({'error': 'Order not found'}, status=404)
        except Exception as e:
            print(f"❌ GET ORDER FILES FAILED: {str(e)}")
            return JsonResponse({'error': f'Failed to get order files: {str(e)}'}, status=500)


    def _get_or_refresh_access_token(self, order):
        """Get valid access token for the order"""
        print(f"=== GETTING ACCESS TOKEN for Order {order.id} ===")
        
        from social_django.models import UserSocialAuth
        
        # Check if we have a valid stored token
        if order.access_token and order.token_expiry and order.token_expiry > timezone.now():
            print("✅ USING EXISTING VALID TOKEN")
            return order.access_token
        
        # Try to refresh the token
        if order.refresh_token:
            print("🔄 REFRESHING TOKEN")
            new_token = self._refresh_oauth_token(order)
            if new_token:
                return new_token
        
        # Try to get from user's social auth
        try:
            print("🔍 CHECKING SOCIAL AUTH")
            social_auth = UserSocialAuth.objects.filter(
                user=order.user, 
                provider='google-oauth2'
            ).first()
            
            if social_auth and social_auth.extra_data.get('access_token'):
                order.access_token = social_auth.extra_data.get('access_token')
                order.refresh_token = social_auth.extra_data.get('refresh_token')
                order.token_expiry = timezone.now() + timezone.timedelta(hours=1)
                order.save(update_fields=['access_token', 'refresh_token', 'token_expiry'])
                print("✅ TOKEN RETRIEVED FROM SOCIAL AUTH")
                return order.access_token
        except Exception as e:
            print(f"❌ SOCIAL AUTH TOKEN FAILED: {e}")
        
        print("❌ NO VALID ACCESS TOKEN AVAILABLE")
        return None


    def _refresh_oauth_token(self, order):
        """Refresh OAuth token if expired"""
        from django.conf import settings
        
        if order.cloud_source == 'google_drive' and order.refresh_token:
            print(f"🔄 REFRESHING GOOGLE OAUTH TOKEN for order {order.id}")
            
            try:
                response = requests.post('https://oauth2.googleapis.com/token', data={
                    'client_id': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY,
                    'client_secret': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET,
                    'refresh_token': order.refresh_token,
                    'grant_type': 'refresh_token'
                }, timeout=30)
                
                if response.status_code == 200:
                    token_data = response.json()
                    new_access_token = token_data.get('access_token')
                    
                    if not new_access_token:
                        raise Exception("No access token received in refresh response")
                    
                    order.access_token = new_access_token
                    order.token_expiry = timezone.now() + timezone.timedelta(
                        seconds=token_data.get('expires_in', 3600)
                    )
                    order.save(update_fields=['access_token', 'token_expiry'])
                    
                    print("✅ TOKEN REFRESHED SUCCESSFULLY")
                    return new_access_token
                else:
                    error_msg = f"Token refresh failed with status {response.status_code}"
                    print(f"❌ {error_msg}: {response.text}")
                    raise Exception(error_msg)
                    
            except requests.exceptions.Timeout:
                error_msg = "Token refresh request timed out"
                print(f"❌ {error_msg}")
                raise Exception(error_msg)
            except Exception as e:
                error_msg = f"Token refresh failed: {str(e)}"
                print(f"❌ {error_msg}")
                raise Exception(error_msg)
        
        return None  
    
    
    @action(detail=False, methods=['get'], url_path=r'direct-download/(?P<order_id>[^/.]+)')
    def direct_download(self, request, order_id=None):
        """Direct download endpoint for browser links"""
        print(f"🔗 DIRECT DOWNLOAD REQUEST: {order_id}")
        
        if not request.user.is_staff:
            messages.error(request, "Admin access required")
            return redirect('admin:login')
        
        try:
            from .models import TransferOrder
            
            order = TransferOrder.objects.get(id=order_id)
            file_selections = order.file_selections.all()
            
            # Get access token
            access_token = self._get_or_refresh_access_token(order)
            if not access_token:
                messages.error(request, "No valid access token")
                return redirect('download-dashboard')
            
            # Update order status
            order.status = 'download_in_progress'
            order.download_status = f'Downloading {file_selections.count()} files...'
            order.save(update_fields=['status', 'download_status', 'updated_at'])
            
            print(f"✅ DIRECT DOWNLOAD STARTING: {file_selections.count()} files")
            
            if file_selections.count() == 1:
                return self._download_single_file_to_client(order, file_selections.first(), access_token)
            else:
                return self._download_multiple_files_as_zip(order, file_selections, access_token)
                
        except Exception as e:
            print(f"❌ DIRECT DOWNLOAD FAILED: {str(e)}")
            messages.error(request, f"Download failed: {str(e)}")
            return redirect('download-dashboard') 
   
   
   
   
   
   


    @action(detail=False, methods=['get', 'post'], url_path=r'transfer/payment')
    def payment_view(self, request):
        """Step 4: Payment Processing with Paystack"""
        base_domain = request.build_absolute_uri('/')
        user = request.user
        
        if not user.is_authenticated:
            return redirect(f'{base_domain}login/')
        
        current_order_id = request.session.get('current_order_id')
        if not current_order_id:
            messages.error(request, "Please complete storage selection first")
            return redirect(f'{base_domain}transfer/storage/')
        
        try:
            from .models import TransferOrder
            order = TransferOrder.objects.get(id=current_order_id, user=user)
            
            if order.status != 'storage_selected':
                messages.error(request, "Please complete storage selection first")
                return redirect(f'{base_domain}transfer/storage/')
            
            context = {
                'base_domain': base_domain,
                'user': user,
                'order': order,
                'current_step': 4,
                'selected_files_count': order.total_files,
                'total_size_gb': float(order.total_size)
            }
            
            if request.method == 'POST':
                return self._handle_payment(request, order, context)
            
            # GET request - show payment page
            context.update(self._get_payment_context(order))
            return render(request, 'payment.html', context)
            
        except TransferOrder.DoesNotExist:
            messages.error(request, "Order not found")
            return redirect(f'{base_domain}transfer/new/')

    def _get_payment_context(self, order):
        """Prepare payment context with calculated amounts"""
        # Calculate pricing based on storage type and size
        base_price = self._calculate_base_price(order.storage_type, order.storage_size)
        shipping_cost = Decimal('4.99')  # Fixed shipping cost
        tax_rate = Decimal('0.08')  # 8% tax
        
        subtotal = base_price
        tax_amount = subtotal * tax_rate
        total_amount = subtotal + shipping_cost + tax_amount
        
        return {
            'order_summary': {
                'storage_type': order.storage_type,
                'storage_size': order.storage_size,
                'files_count': order.total_files,
                'total_size': f"{order.total_size:.1f} GB",
                'subtotal': f"{subtotal:.2f}",
                'shipping': f"{shipping_cost:.2f}",
                'tax': f"{tax_amount:.2f}",
                'total': f"{total_amount:.2f}",
            },
            'payment_methods': [
                {'id': 'card', 'name': 'Credit/Debit Card', 'icon': 'credit-card', 'description': 'Pay securely with your card'},
                {'id': 'bank', 'name': 'Bank Transfer', 'icon': 'university', 'description': 'Transfer directly from your bank'},
                {'id': 'mobile', 'name': 'Mobile Money', 'icon': 'mobile-alt', 'description': 'Pay with mobile money'},
            ],
            'paystack_public_key': 'pk_test_dummy_key_1234567890',  # Dummy key for development
            'order_reference': f"ORD-{order.id}-{order.created_at.strftime('%Y%m%d')}",
        }

    def _calculate_base_price(self, storage_type, storage_size):
        """Calculate base price based on storage selection"""
        size_gb = int(storage_size.replace('GB', '').strip())
        
        # Base prices per GB for different storage types
        price_per_gb = {
            'flash_drive': Decimal('2.50'),
            'memory_card': Decimal('3.00'),
            'external_hdd': Decimal('1.75')
        }
        
        base_price = price_per_gb.get(storage_type, Decimal('2.00')) * size_gb
        return max(base_price, Decimal('9.99'))  # Minimum charge

    def _handle_payment(self, request, order, context):
        """Handle payment form submission"""
        payment_method = request.POST.get('payment_method')
        email = request.POST.get('email')
        amount = request.POST.get('amount')
        
        if not all([payment_method, email, amount]):
            messages.error(request, "Please fill all required fields")
            context.update(self._get_payment_context(order))
            return render(request, 'payment.html', context)
        
        try:
            # Initialize Paystack payment (dummy implementation)
            payment_data = self._initialize_paystack_payment(
                email=email,
                amount=amount,
                order=order
            )
            
            if payment_data.get('status'):
                # Store payment reference in session
                request.session['payment_reference'] = payment_data['data']['reference']
                request.session['order_id'] = order.id
                
                # Redirect to Paystack payment page (dummy for now)
                messages.success(request, "Payment initialized successfully")
                return redirect(payment_data['data']['authorization_url'])
            else:
                messages.error(request, f"Payment initialization failed: {payment_data.get('message', 'Unknown error')}")
                context.update(self._get_payment_context(order))
                return render(request, 'payment.html', context)
                
        except Exception as e:
            messages.error(request, f"Payment error: {str(e)}")
            context.update(self._get_payment_context(order))
            return render(request, 'payment.html', context)

    def _initialize_paystack_payment(self, email, amount, order):
        """
        Initialize Paystack payment (dummy implementation)
        In production, this would make actual API call to Paystack
        """
        # Dummy Paystack response structure
        return {
            "status": True,
            "message": "Authorization URL created",
            "data": {
                "authorization_url": "https://checkout.paystack.com/dummy_checkout_page",
                "access_code": "dummy_access_code_123",
                "reference": f"paystack_ref_{order.id}_{order.created_at.strftime('%Y%m%d%H%M%S')}"
            }
        }

    @csrf_exempt
    def paystack_webhook(self, request):
        """Handle Paystack webhook for payment verification"""
        if request.method == 'POST':
            try:
                # Dummy webhook processing
                payload = json.loads(request.body)
                reference = payload.get('data', {}).get('reference')
                
                if payload.get('event') == 'charge.success':
                    # Verify payment with Paystack (dummy)
                    verification_result = self._verify_paystack_payment(reference)
                    
                    if verification_result.get('status'):
                        # Update order status
                        from .models import TransferOrder
                        order_id = request.session.get('order_id')
                        if order_id:
                            order = TransferOrder.objects.get(id=order_id)
                            order.status = 'payment_completed'
                            order.payment_reference = reference
                            order.save()
                            
                            # Clear session
                            request.session.pop('current_order_id', None)
                            request.session.pop('payment_reference', None)
                            request.session.pop('order_id', None)
                            
                            return JsonResponse({'status': 'success'})
                
                return JsonResponse({'status': 'ignored'})
                
            except Exception as e:
                return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
        
        return JsonResponse({'status': 'invalid_method'}, status=405)

    def _verify_paystack_payment(self, reference):
        """Verify Paystack payment (dummy implementation)"""
        # Dummy verification response
        return {
            "status": True,
            "message": "Verification successful",
            "data": {
                "reference": reference,
                "status": "success",
                "amount": 100000,  # Amount in kobo
                "currency": "NGN",
                "gateway_response": "Successful"
            }
        }