from django.shortcuts import render, redirect
from django.contrib import messages
from django.db.models import Q
from rest_framework import viewsets
from rest_framework.decorators import action
from .. models import TransferOrder

from .base import DummySerializer


def format_file_size(bytes_size):
    """Convert bytes to human readable format (KB, MB, GB, TB)"""
    if bytes_size == 0 or bytes_size is None:
        return "0 B"
    
    size_units = ['B', 'KB', 'MB', 'GB', 'TB']
    size = float(bytes_size)
    unit_index = 0
    
    while size >= 1024 and unit_index < len(size_units) - 1:
        size /= 1024
        unit_index += 1
    
    return f"{size:.2f} {size_units[unit_index]}"




class ClientOrderStatusViewSet(viewsets.ModelViewSet):
    """Handles displaying order status and details to clients"""
    serializer_class = DummySerializer
    
    @action(detail=False, methods=['get']) # url_path=r'status/(?P<order_id>[^/.]+)'
    def order_status(self, request, order_id=None):
        """Display comprehensive order status and details to client"""
        base_domain = request.build_absolute_uri('/')
        user = request.user
        
        if not user.is_authenticated:
            return redirect(f'{base_domain}login/')
        
        try:
            # Check if user is admin - can view any order
            if user.is_staff:
                order = TransferOrder.objects.get(order_number=order_id)
            else:
                # Regular user - can only view their own orders
                order = TransferOrder.objects.get(
                    order_number=order_id,
                    user=user
                )
            
            # Prepare order context with all required information
            context = {
                'base_domain': base_domain,
                'user': user,
                'order': order,
                'order_details': self._get_order_details(order),
                'status_info': self._get_status_information(order),
                'progress_data': self._get_progress_data(order),
                'timeline_events': self._get_timeline_events(order),
                'file_details': self._get_file_details(order),  # Add file details
                'file_summary': self._get_file_summary(order),  # Add file summary
                'is_admin': user.is_staff,  # Add admin flag
                'status_choices': TransferOrder.STATUS_CHOICES if user.is_staff else None  # Add status choices for admin
            }
            
            return render(request, 'client_detailed_order_status.html', context)
        
        except TransferOrder.DoesNotExist:
            messages.error(request, "Order not found or you don't have permission to view this order.")
            print("ERROR OCCURRED HERE")
            return redirect(f'{base_domain}transfer/orders/')
        except Exception as e:
            print(f"Error retrieving order: {e}")
            messages.error(request, "An error occurred while retrieving order details.")
            return redirect(f'{base_domain}transfer/orders/')
            
           
    
    def _get_order_details(self, order):
        """Extract and format comprehensive order details"""
        total_size_bytes = float(order.total_size) * (1024 ** 3)
        
        return {
            'order_id': order.display_id,
            'cloud_service': self._get_cloud_service_display(order.cloud_source),
            'storage_device': self._get_storage_device_display(order),
            'total_file_size': format_file_size(total_size_bytes),  # Convert GB to bytes for formatting
            'file_count': order.total_files,
            'payment_currency': order.payment_currency,
            'payment_status': self._get_payment_status(order),
            'payment_amount': f"{order.payment_amount} {order.payment_currency}",
            'download_status': self._get_download_status(order),
            'shipping_address': order.shipping_address or "Not provided yet",
            'created_date': order.created_at,
            'last_updated': order.updated_at
        }
        
        
    def _get_status_information(self, order):
        """Get detailed status information with user-friendly messages"""
        status_messages = {
            'cloud_connected': {
                'title': 'Cloud Connected',
                'message': 'Your cloud storage has been successfully connected.',
                'icon': 'fas fa-cloud-check',
                'color': 'text-blue-600',
                'bg_color': 'bg-blue-50'
            },
            'files_selected': {
                'title': 'Files Selected',
                'message': f'You have selected {order.total_files} files totaling {order.total_size} GB.',
                'icon': 'fas fa-file-check',
                'color': 'text-green-600',
                'bg_color': 'bg-green-50'
            },
            'storage_selected': {
                'title': 'Storage Selected',
                'message': f'{order.get_storage_type_display()} selected for your files.',
                'icon': 'fas fa-hdd',
                'color': 'text-purple-600',
                'bg_color': 'bg-purple-50'
            },
            'payment_completed': {
                'title': 'Payment Completed',
                'message': f'Payment of {order.payment_amount} {order.payment_currency} has been processed successfully.',
                'icon': 'fas fa-check-circle',
                'color': 'text-green-600',
                'bg_color': 'bg-green-50'
            },
            'payment_pending': {
                'title': 'Payment Pending',
                'message': 'Waiting for payment confirmation.',
                'icon': 'fas fa-clock',
                'color': 'text-yellow-600',
                'bg_color': 'bg-yellow-50'
            },
            'download_in_progress': {
                'title': 'Download in Progress',
                'message': order.download_status or 'Your files are being downloaded from cloud storage.',
                'icon': 'fas fa-download',
                'color': 'text-blue-600',
                'bg_color': 'bg-blue-50'
            },
            'download_completed': {
                'title': 'Download Completed',
                'message': f'All files downloaded successfully on {order.download_completed_at}.',
                'icon': 'fas fa-check-double',
                'color': 'text-green-600',
                'bg_color': 'bg-green-50'
            },
            'download_failed': {
                'title': 'Download Failed',
                'message': order.download_status or 'There was an issue downloading your files. Our team has been notified.',
                'icon': 'fas fa-exclamation-triangle',
                'color': 'text-red-600',
                'bg_color': 'bg-red-50'
            },
            'download_partial': {
                'title': 'Partial Download',
                'message': order.download_status or 'Some files were downloaded successfully, but others failed.',
                'icon': 'fas fa-exclamation-circle',
                'color': 'text-orange-600',
                'bg_color': 'bg-orange-50'
            },
            'processing': {
                'title': 'Processing Files',
                'message': 'Your files are being processed and prepared for storage.',
                'icon': 'fas fa-cogs',
                'color': 'text-indigo-600',
                'bg_color': 'bg-indigo-50'
            },
            'shipped': {
                'title': 'Order Shipped',
                'message': 'Your storage device has been shipped and is on its way to you.',
                'icon': 'fas fa-shipping-fast',
                'color': 'text-teal-600',
                'bg_color': 'bg-teal-50'
            },
            'delivered': {
                'title': 'Delivered',
                'message': 'Your storage device has been delivered to your shipping address.',
                'icon': 'fas fa-box-open',
                'color': 'text-green-600',
                'bg_color': 'bg-green-50'
            },
            'completed': {
                'title': 'Order Completed',
                'message': 'Your order has been successfully completed.',
                'icon': 'fas fa-flag-checkered',
                'color': 'text-green-600',
                'bg_color': 'bg-green-50'
            },
            'cancelled': {
                'title': 'Order Cancelled',
                'message': 'This order has been cancelled.',
                'icon': 'fas fa-ban',
                'color': 'text-red-600',
                'bg_color': 'bg-red-50'
            }
        }
        
        return status_messages.get(order.status, {
            'title': order.get_status_display(),
            'message': 'Your order is being processed.',
            'icon': 'fas fa-info-circle',
            'color': 'text-gray-600',
            'bg_color': 'bg-gray-50'
        })
    
    
    def _get_progress_data(self, order):
        """Calculate progress through order workflow with proper status mapping"""
        
        # Define the progress steps in order
        progress_steps = [
            'cloud_connected',
            'files_selected', 
            'storage_selected',
            'payment_completed',
            'download_completed',
            'processing',
            'shipped',
            'delivered',
            'completed'
        ]
        
        # Map all possible statuses to their progress level
        status_to_step = {
            'cloud_connected': 0,
            'files_selected': 1,
            'storage_selected': 2,
            'payment_pending': 2,  # Same as storage_selected
            'payment_completed': 3,
            'download_queued': 3,  # Same as payment_completed
            'download_in_progress': 3,
            'download_completed': 4,
            'download_failed': 3,  # Back to payment_completed level
            'download_partial': 3,  # Back to payment_completed level
            'processing': 5,
            'shipped': 6,
            'delivered': 7,
            'completed': 8,
            'cancelled': 0  # Or handle separately
        }
        
        # Get current step index
        current_step_index = status_to_step.get(order.status, 0)
        
        # Create steps list with names
        steps_with_names = []
        step_names = {
            'cloud_connected': 'Cloud Connected',
            'files_selected': 'Files Selected',
            'storage_selected': 'Storage Selected',
            'payment_completed': 'Payment Completed',
            'download_completed': 'Files Downloaded',
            'processing': 'Processing',
            'shipped': 'Shipped',
            'delivered': 'Delivered',
            'completed': 'Completed'
        }
        
        for step_status in progress_steps:
            steps_with_names.append({
                'name': step_names[step_status],
                'status': step_status
            })
        
        # Calculate progress percentage
        progress_percentage = int((current_step_index / (len(progress_steps) - 1)) * 100) if len(progress_steps) > 1 else 0
        
        return {
            'current_step': current_step_index,
            'total_steps': len(progress_steps),
            'percentage': progress_percentage,
            'steps': steps_with_names,
            'current_step_name': steps_with_names[current_step_index]['name'] if current_step_index < len(steps_with_names) else 'Processing'
        }  
    

    def _get_timeline_events(self, order):
        """Generate comprehensive timeline of all order events"""
        timeline = []
        
        # Format file size helper
        def format_size(bytes_size):
            if bytes_size == 0 or bytes_size is None:
                return "0 GB"
            size = float(bytes_size) * (1024 ** 3) if bytes_size < 1000 else float(bytes_size)
            if size < 1024:
                return f"{size:.2f} B"
            elif size < 1024 * 1024:
                return f"{size/1024:.2f} KB"
            elif size < 1024 * 1024 * 1024:
                return f"{size/(1024*1024):.2f} MB"
            else:
                return f"{size/(1024*1024*1024):.2f} GB"
        
        total_size_display = format_size(float(order.total_size))
        
        # 1. Order Created
        timeline.append({
            'date': order.created_at,
            'title': 'Order Created',
            'description': f'Order {order.display_id} was created successfully.',
            'icon': 'fa-shopping-cart',
            'status': 'completed'
        })
        
        # 2. Cloud Connected
        if order.status in ['cloud_connected', 'files_selected', 'storage_selected', 'payment_completed', 
                        'payment_pending', 'download_in_progress', 'download_completed', 'download_failed', 
                        'download_partial', 'processing', 'shipped', 'delivered', 'completed']:
            
            timeline.append({
                'date': order.created_at or order.updated_at,
                'title': 'Cloud Storage Connected',
                'description': f'{self._get_cloud_service_display(order.cloud_source)} was successfully connected to your account.',
                'icon': 'fa-cloud',
                'status': 'completed'
        })
        
        # 3. Files Selected
        if order.status in ['files_selected', 'storage_selected', 'payment_completed', 'payment_pending', 
                        'download_in_progress', 'download_completed', 'download_failed', 'download_partial', 
                        'processing', 'shipped', 'delivered', 'completed'] and order.total_files > 0:
            timeline.append({
                'date': order.updated_at,
                'title': 'Files Selected',
                'description': f'{order.total_files} files ({total_size_display}) were selected for transfer.',
                'icon': 'fa-file-import',
                'status': 'completed'
            })
        
        # 4. Storage Device Selected
        if order.status in ['storage_selected', 'payment_completed', 'payment_pending', 'download_in_progress', 
                        'download_completed', 'download_failed', 'download_partial', 'processing', 'shipped', 
                        'delivered', 'completed'] and order.storage_type:
            storage_display = dict(TransferOrder.STORAGE_CHOICES).get(order.storage_type, order.storage_type)
            timeline.append({
                'date': order.updated_at,
                'title': 'Storage Device Selected',
                'description': f'{storage_display} ({order.storage_size}) was selected for your files.',
                'icon': 'fa-hdd',
                'status': 'completed'
            })
        
        # 5. Payment Status Events
        if order.status == 'payment_pending':
            timeline.append({
                'date': order.updated_at,
                'title': 'Payment Pending',
                'description': f'Payment of {order.payment_amount} {order.payment_currency} is awaiting confirmation.',
                'icon': 'fa-clock',
                'status': 'pending'
            })
        
        if order.status in ['payment_completed', 'download_in_progress', 'download_completed', 'download_failed', 
                        'download_partial', 'processing', 'shipped', 'delivered', 'completed'] and order.payment_amount > 0:
            timeline.append({
                'date': order.updated_at,
                'title': 'Payment Completed',
                'description': f'Payment of {order.payment_amount} {order.payment_currency} was successfully processed.',
                'icon': 'fa-credit-card',
                'status': 'completed'
            })
        
        # 6. Download Events
        if order.download_started_at:
            timeline.append({
            'date': order.download_started_at,
            'title': 'Document References Prepared',
            'description': f'References to {order.total_files} files from {self._get_cloud_service_display(order.cloud_source)} have been successfully identified and queued for processing.',
            'icon': 'fa-download',
            'status': 'in_progress'
        })
                
        if order.download_completed_at:
            timeline.append({
                'date': order.download_completed_at,
                'title': 'File Reference Verification Completed',
                'description': f'The system successfully finalized and verified references for {order.total_files} files with a total processed size of {total_size_display}.',
                'icon': 'fa-check-circle',
                'status': 'completed'
            })
        
        # 7. Download Failed/Partial Events
        if order.status == 'download_failed':
            timeline.append({
                'date': order.updated_at,
                'title': 'Download Failed',
                'description': order.download_status or 'The download process encountered an error. Our team has been notified.',
                'icon': 'fa-exclamation-triangle',
                'status': 'failed'
            })
        
        if order.status == 'download_partial':
            downloaded_count = order.total_downloaded_files
            timeline.append({
                'date': order.updated_at,
                'title': 'Partial Download Completed',
                'description': f'{downloaded_count} out of {order.total_files_count} files were downloaded successfully.',
                'icon': 'fa-exclamation-circle',
                'status': 'warning'
            })
        
        # 8. Processing Events
        if order.status == 'processing':
            timeline.append({
                'date': order.updated_at,
                'title': 'Processing Files',
                'description': 'Your files are being processed and prepared for transfer to storage device.',
                'icon': 'fa-cogs',
                'status': 'in_progress'
            })
        
        # 9. Shipping Events
        if order.status == 'shipped':
            timeline.append({
                'date': order.updated_at,
                'title': 'Order Shipped',
                'description': 'Your storage device has been shipped to your address.',
                'icon': 'fa-shipping-fast',
                'status': 'completed'
            })
        
        # 10. Delivered Event
        if order.status == 'delivered':
            timeline.append({
                'date': order.updated_at,
                'title': 'Order Delivered',
                'description': 'Your storage device has been delivered to your shipping address.',
                'icon': 'fa-box-open',
                'status': 'completed'
            })
        
        # 11. Completed Event
        if order.status == 'completed':
            timeline.append({
                'date': order.updated_at,
                'title': 'Order Completed',
                'description': 'Your order has been successfully completed. Thank you for using CloudTransfer!',
                'icon': 'fa-flag-checkered',
                'status': 'completed'
            })
        
        # 12. Cancelled Event
        if order.status == 'cancelled':
            timeline.append({
                'date': order.updated_at,
                'title': 'Order Cancelled',
                'description': 'This order has been cancelled.',
                'icon': 'fa-ban',
                'status': 'cancelled'
            })
        
        # Add retry events if any
        if order.retry_count > 0:
            timeline.append({
                'date': order.updated_at,
                'title': f'Download Retry #{order.retry_count}',
                'description': f'The download process was automatically retried {order.retry_count} time(s).',
                'icon': 'fa-sync-alt',
                'status': 'warning'
            })
        
        # Remove duplicate events (keep the most recent of similar events)
        unique_timeline = []
        seen_titles = set()
        
        for event in reversed(timeline):  # Reverse to keep most recent
            if event['title'] not in seen_titles:
                seen_titles.add(event['title'])
                unique_timeline.append(event)
        
        # Reverse back to chronological order
        unique_timeline.reverse()
        
        # Sort by date
        unique_timeline.sort(key=lambda x: x['date'])
        
        return unique_timeline

 
    def _get_cloud_service_display(self, cloud_source):
        """Get user-friendly cloud service name"""
        cloud_services = {
            'google_drive': 'Google Drive',
            'dropbox': 'Dropbox',
            'onedrive': 'OneDrive'
        }
        return cloud_services.get(cloud_source, cloud_source)
    
    def _get_storage_device_display(self, order):
        """Get user-friendly storage device name"""
        if order.storage_type:
            storage_devices = {
                'flash_drive': f'USB Flash Drive ({order.storage_size})',
                'memory_card': f'Memory Card ({order.storage_size})',
                'external_hdd': f'External Hard Drive ({order.storage_size})'
            }
            return storage_devices.get(order.storage_type, order.get_storage_type_display())
        return "Not selected yet"
    
    def _get_payment_status(self, order):
        """Determine payment status based on order status"""
        if order.status in ['payment_completed', 'download_in_progress', 'download_completed',
                           'download_failed', 'download_partial', 'processing', 'shipped',
                           'delivered', 'completed']:
            return 'Completed'
        elif order.status == 'payment_pending':
            return 'Pending'
        else:
            return 'Not Required Yet'
    
    def _get_download_status(self, order):
        """Get detailed download status"""
        if order.download_completed_at:
            return f'Completed on {order.download_completed_at}'
        elif order.download_started_at:
            return f'In Progress - Started {order.download_started_at}'
        elif order.status in ['payment_completed', 'storage_selected']:
            return 'Ready to Download'
        else:
            return 'Not Started'
    
    def _is_status_achieved(self, current_status, target_status):
        """Check if a status step has been achieved in the workflow"""
        status_hierarchy = [
            'cloud_connected',
            'files_selected', 
            'storage_selected',
            'payment_completed',
            'download_completed',
            'processing',
            'shipped',
            'delivered',
            'completed'
        ]
        
        try:
            current_index = status_hierarchy.index(current_status)
            target_index = status_hierarchy.index(target_status)
            return current_index >= target_index
        except ValueError:
            return False
    



    @action(detail=False, methods=['get']) # url_path=r'transfer/orders'
    def user_orders(self, request):
        """Display all orders for the current user (or all orders for admin)"""
        base_domain = request.build_absolute_uri('/')
        user = request.user
        
        if not user.is_authenticated:
            return redirect(f'{base_domain}login/')
        
        # Admin can see all orders, regular users only see their own
        if user.is_staff:
            orders = TransferOrder.objects.all().order_by('-created_at')
        else:
            orders = TransferOrder.objects.filter(user=user).order_by('-created_at')
        
        context = {
            'base_domain': base_domain,
            'user': user,
            'orders': orders,
            'orders_count': orders.count(),
            'is_admin': user.is_staff
        }
        
        return render(request, 'client_order_status.html', context)
        
    
    @action(detail=True, methods=['post'])
    def update_order_status(self, request, order_id=None):
        """Admin endpoint to update order status"""
        base_domain = request.build_absolute_uri('/')
        user = request.user
        
        if not user.is_authenticated:
            return redirect(f'{base_domain}login/')
        
        if not user.is_staff:
            messages.error(request, "Admin access required.")
            return redirect(f'{base_domain}transfer/status/{order_id}/')
        
        try:
            order = TransferOrder.objects.get(order_number=order_id)
            new_status = request.POST.get('status')
            
            if new_status in dict(TransferOrder.STATUS_CHOICES):
                order.status = new_status
                order.save()
                messages.success(request, f"Order status updated to {order.get_status_display()}")
            else:
                messages.error(request, "Invalid status selected.")
                
        except TransferOrder.DoesNotExist:
            messages.error(request, "Order not found.")
        
        return redirect(f'{base_domain}transfer/status/{order_id}/')
    

    def _get_file_details(self, order):
        """Get detailed file information with download status"""
        files = []
        for file_selection in order.file_selections.all():
            files.append({
                'id': str(file_selection.id),
                'name': file_selection.file_name,
                'size': file_selection.file_size,
                'formatted_size': format_file_size(file_selection.file_size),
                'status': file_selection.download_status,
                'downloaded_at': file_selection.downloaded_at,
                'error_message': file_selection.download_error,
                'progress': file_selection.progress_percentage
            })
        return files
    

    def _get_file_summary(self, order):
        """Get summary of file download status"""
        total_files = order.file_selections.count()
        downloaded = order.file_selections.filter(download_status='downloaded').count()
        failed = order.file_selections.filter(download_status='failed').count()
        pending = order.file_selections.filter(download_status='pending').count()
        in_progress = order.file_selections.filter(download_status='downloading').count()
        
        return {
            'total': total_files,
            'downloaded': downloaded,
            'failed': failed,
            'pending': pending,
            'in_progress': in_progress,
            'has_failed': failed > 0,
            'has_pending': pending > 0,
            'is_complete': downloaded == total_files and total_files > 0,
            'is_partial': downloaded > 0 and downloaded < total_files
        }