from django.shortcuts import render, redirect
from django.contrib import messages
from django.db import transaction
from rest_framework import viewsets
from rest_framework.decorators import action

from .base import DummySerializer



class StorageViewSet(viewsets.ModelViewSet):
    """Handles connecting and displaying cloud storage accounts (Google Drive, Dropbox, OneDrive)"""
    serializer_class = DummySerializer
    
    
    #### THIS HANDLES THE STORAGE SELECTION WITH SMART RECOMMENDATIONS ##########
    @action(detail=False, methods=['get', 'post'], url_path=r'')
    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 _handle_storage_selection(self, request, order, context):
        """Handle storage selection form submission with Kenyan address - FIXED VERSION"""
        print("=== STORAGE SELECTION HANDLER STARTED ===")
        
        base_domain = request.build_absolute_uri('/')
        storage_type = request.POST.get('storage_type')
        storage_size = request.POST.get('storage_size')
        
        print(f"DEBUG: storage_type = {storage_type}")
        print(f"DEBUG: storage_size = {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', '')
        
        print(f"DEBUG: county = {county}, district = {district}, town = {town}")
        print(f"DEBUG: street_address = {street_address}")
        
        # Validate required fields
        required_fields = [storage_type, storage_size, county, district, street_address, town]
        print(f"DEBUG: Required fields check: {required_fields}")
        print(f"DEBUG: All fields present? {all(required_fields)}")
        
        if not all(required_fields):
            print("ERROR: Missing 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)
        
        print("DEBUG: All required fields present")
        
        # Validate storage size
        try:
            required_gb = context['minimum_required_gb']
            print(f"DEBUG: Minimum required GB from context: {required_gb}")
            
            # Parse storage size - handle both GB and TB
            storage_size_clean = storage_size.upper().strip()
            print(f"DEBUG: Clean storage size: {storage_size_clean}")
            
            if 'TB' in storage_size_clean:
                # Convert TB to GB (1TB = 1000GB)
                tb_value = float(storage_size_clean.replace('TB', '').strip())
                selected_gb = int(tb_value * 1000)
                storage_size_for_db = storage_size_clean
                print(f"DEBUG: Converted {tb_value}TB to {selected_gb}GB")
            elif 'GB' in storage_size_clean:
                # Already in GB
                selected_gb = int(storage_size_clean.replace('GB', '').strip())
                storage_size_for_db = storage_size_clean
                print(f"DEBUG: Parsed {selected_gb}GB directly")
            else:
                # Assume it's in GB if no unit specified
                selected_gb = int(storage_size_clean)
                storage_size_for_db = f"{selected_gb}GB"
                print(f"DEBUG: No unit specified, assuming GB: {selected_gb}GB")
            
            print(f"DEBUG: Selected GB after parsing: {selected_gb}")
            print(f"DEBUG: Storage size for DB: {storage_size_for_db}")
            
            if selected_gb < required_gb:
                print(f"ERROR: Selected GB ({selected_gb}) < Required 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)
            
            print("DEBUG: Storage size validation passed")
            
            # 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}"
            
            print(f"DEBUG: Shipping address built: {shipping_address[:100]}...")
            
            # UPDATE ORDER WITH TRANSACTION ATOMIC FOR DATA CONSISTENCY
            from django.db import transaction
            
            try:
                print("DEBUG: Starting transaction for order update")
                with transaction.atomic():
                    # Update order fields
                    order.storage_type = storage_type
                    order.storage_size = storage_size_for_db  # Use the properly formatted size
                    order.shipping_address = shipping_address
                    order.status = 'storage_selected'
                    
                    print(f"DEBUG: Order update - storage_type: {storage_type}")
                    print(f"DEBUG: Order update - storage_size: {storage_size_for_db}")
                    print(f"DEBUG: Order update - 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
                    ])
                    
                    print("DEBUG: Order saved successfully")
                    
                    # Verify the save worked
                    order.refresh_from_db()
                    print(f"DEBUG: Refreshed order status: {order.status}")
                    print(f"DEBUG: Refreshed order storage_size: {order.storage_size}")
                    
                    if order.status != 'storage_selected':
                        print("ERROR: Order status not updated correctly after save")
                        raise Exception("Order not updated correctly")
                    
                    print("DEBUG: Order verification passed")
                    print(f"DEBUG: Redirecting to: {base_domain}transfer/payment/")
                    
                    return redirect(f'{base_domain}transfer/payment/')
                    
            except Exception as e:
                print(f"ERROR IN TRANSACTION: {type(e).__name__}: {str(e)}")
                messages.error(request, "Failed to save your selection. Please try again.")
                # Log the error for debugging
                print(f"Full error saving order: {e}")
                import traceback
                print(f"Traceback: {traceback.format_exc()}")
                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:
            print(f"ERROR PARSING STORAGE SIZE: {type(e).__name__}: {str(e)}")
            messages.error(request, "Invalid storage size selected. Please enter a valid size like '1TB' or '500GB'")
            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)
        
        finally:
            print("=== STORAGE SELECTION HANDLER ENDED ===")
        
         



    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'
        ]
    