from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import AdminPasswordChangeForm
from django.contrib import messages
from django.core.exceptions import ValidationError
from django.shortcuts import redirect, render
from django.template.response import TemplateResponse
from django.urls import path, reverse
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from .models import User, Address, Wishlist, VerificationCode
from vendors.models import Vendor
from django.core.mail import send_mail
from django.conf import settings
from django.contrib.admin import helpers
from ai_features.models import AIConfiguration, CommunicationTemplate
import json
from django.core.serializers.json import DjangoJSONEncoder
from django.template import Context, Template

@admin.register(VerificationCode)
class VerificationCodeAdmin(admin.ModelAdmin):
    list_display = ('user', 'channel', 'code', 'is_used', 'attempts', 'expires_at', 'created_at')
    list_filter = ('channel', 'is_used', 'created_at')
    search_fields = ('user__email', 'user__phone', 'code')
    readonly_fields = ('created_at',)
    ordering = ('-created_at',)

class VerificationCodeInline(admin.TabularInline):
    model = VerificationCode
    extra = 0
    readonly_fields = ('created_at', 'expires_at', 'code', 'is_used', 'attempts', 'channel', 'contact_value')
    can_delete = False
    ordering = ('-created_at',)

class VendorInline(admin.StackedInline):
    model = Vendor
    extra = 0
    can_delete = False
    verbose_name = 'Vendor Profile'
    verbose_name_plural = 'Vendor Profile'
    fieldsets = (
        ('Store Information', {
            'fields': ('store_name', 'business_name', 'status')
        }),
        ('KYC Documents', {
            'fields': ('aadhaar_no', 'gst_no', 'consent_form', 'gst_photo', 'kyc_photo', 'kyc_address_proof', 'kyc_submitted', 'kyc_approved')
        })
    )
    readonly_fields = ('kyc_submitted',)

class UserAdminForm(forms.ModelForm):
    class Meta:
        model = User
        fields = "__all__"

    def clean(self):
        cleaned_data = super().clean()
        try:
            kyc_changed = self.has_changed() and ('kyc_approved' in self.changed_data)
        except Exception:
            kyc_changed = bool(cleaned_data.get("kyc_approved"))
        if kyc_changed and cleaned_data.get("kyc_approved"):
            errors = {}
            if not (cleaned_data.get("aadhaar_no") or "").strip():
                errors["aadhaar_no"] = "Required"
            if not cleaned_data.get("consent_form"):
                errors["consent_form"] = "Required"
            if not cleaned_data.get("kyc_photo"):
                errors["kyc_photo"] = "Required"
            if not cleaned_data.get("kyc_address_proof"):
                errors["kyc_address_proof"] = "Required"
            if errors:
                raise ValidationError(errors)
        return cleaned_data


@admin.register(User)
class UserAdmin(BaseUserAdmin):
    """Custom User Admin with Role Management"""
    
    form = UserAdminForm
    inlines = [VerificationCodeInline, VendorInline]

    list_display = (
        'email',  'full_name', 'role', 'email_verified', 'phone_verified', 'is_verified',
        'is_active', 'is_staff', 'created_at'
    )
    list_filter = ('role', 'is_staff', 'is_superuser', 'is_active', 'is_verified', 'email_verified', 'phone_verified')
    search_fields = ('email', 'first_name', 'last_name', 'phone')
    ordering = ('-created_at',)
    
    fieldsets = (
        (None, {'fields': ('email', 'password', 'change_password_link')}),
        (_('Personal Info'), {
            'fields': (
                'first_name', 'last_name', 'phone', 'date_of_birth',
                'profile_picture'
            )
        }),
        (_('Address'), {
            'fields': ('address', 'city', 'state', 'country', 'pincode')
        }),
        (_('Staff/User KYC (Not for Vendors)'), {
            'fields': ('aadhaar_no', 'consent_form', 'kyc_photo', 'kyc_address_proof', 'kyc_submitted', 'kyc_approved')
        }),
        (_('Permissions'), {
            'fields': (
                'role', 'is_active', 'is_staff', 'is_superuser',
                'email_verified', 'phone_verified', 'is_verified',
                'groups', 'user_permissions'
            ),
        }),
        (_('Important dates'), {'fields': ('last_login', 'created_at', 'updated_at')}),
    )
    
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': (
                'email', 'password1', 'password2', 'role',
                'first_name', 'last_name', 'is_staff', 'is_active'
            ),
        }),
    )
    
    readonly_fields = ('created_at', 'updated_at', 'last_login', 'change_password_link')
    def get_readonly_fields(self, request, obj=None):
        ro = list(super().get_readonly_fields(request, obj))
        if obj and obj.kyc_approved:
            ro += ['aadhaar_no', 'gst_no', 'consent_form', 'kyc_photo', 'kyc_address_proof']
        return ro
    
    def save_model(self, request, obj, form, change):
        super().save_model(request, obj, form, change)
    
    actions = ['verify_users', 'deactivate_users', 'make_staff', 'make_customer', 'send_email_action', 'send_sms_action', 'send_whatsapp_action']
    
    def _get_rendered_message(self, message, user):
        """Helper to render message variables"""
        try:
            template = Template(message)
            context = Context({'user': user})
            return template.render(context)
        except Exception:
            return message

    def _send_communication_view(self, request, queryset, type_key):
        """Unified view for sending Email, SMS, or WhatsApp"""
        type_labels = {
            'email': 'Email',
            'sms': 'SMS',
            'whatsapp': 'WhatsApp'
        }
        type_label = type_labels.get(type_key, 'Message')
        action_name = f'send_{type_key}_action'
        
        # Fetch active templates for this type
        templates = CommunicationTemplate.objects.filter(type=type_key, is_active=True)
        templates_data = {
            str(t.id): {
                'content': t.content, 
                'subject': t.subject,
                'category': t.category
            } for t in templates
        }

        if 'apply' in request.POST:
            message = request.POST.get('message')
            subject = request.POST.get('subject') # Only for email
            
            if message:
                count = 0
                success_count = 0
                
                # Setup configuration
                config = AIConfiguration.get_settings()
                
                # Twilio setup for SMS/WhatsApp
                twilio_client = None
                twilio_from = None
                if type_key in ['sms', 'whatsapp']:
                    try:
                        from twilio.rest import Client
                        if config.twilio_account_sid and config.twilio_auth_token and config.twilio_phone_number:
                            twilio_client = Client(config.twilio_account_sid, config.twilio_auth_token)
                            twilio_from = config.twilio_phone_number
                    except ImportError:
                        self.message_user(request, "Twilio library not installed.", level=messages.ERROR)
                        return redirect(request.get_full_path())
                    except Exception as e:
                        self.message_user(request, f"Twilio configuration error: {e}", level=messages.ERROR)
                        return redirect(request.get_full_path())

                # Email Sender
                from_email = None
                if type_key == 'email':
                     try:
                        from_email = (config.email_from_address if config and config.email_from_address else getattr(settings, 'DEFAULT_FROM_EMAIL', 'no-reply@aibimagics.com'))
                     except Exception:
                        from_email = getattr(settings, 'DEFAULT_FROM_EMAIL', 'no-reply@aibimagics.com')

                for user in queryset:
                    rendered_msg = self._get_rendered_message(message, user)
                    
                    try:
                        if type_key == 'email':
                            if user.email and subject:
                                send_mail(subject, rendered_msg, from_email, [user.email], fail_silently=False)
                                success_count += 1
                                
                        elif type_key == 'sms':
                            if user.phone and twilio_client:
                                twilio_client.messages.create(
                                    body=rendered_msg,
                                    from_=twilio_from,
                                    to=user.phone
                                )
                                success_count += 1
                                
                        elif type_key == 'whatsapp':
                            if user.phone and twilio_client:
                                # Ensure number has whatsapp: prefix for Twilio
                                to_num = f"whatsapp:{user.phone}" if not user.phone.startswith('whatsapp:') else user.phone
                                from_num = f"whatsapp:{twilio_from}" if not twilio_from.startswith('whatsapp:') else twilio_from
                                
                                twilio_client.messages.create(
                                    body=rendered_msg,
                                    from_=from_num,
                                    to=to_num
                                )
                                success_count += 1
                                
                    except Exception as e:
                        # Log error but continue
                        pass
                    
                    count += 1
                
                self.message_user(request, f"Successfully sent {type_label} to {success_count} out of {count} users.")
                return redirect(request.get_full_path())
        
        context = {
            'queryset': queryset,
            'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
            'opts': self.model._meta,
            'action_name': action_name,
            'type_label': type_label,
            'templates': templates,
            'templates_json': json.dumps(templates_data, cls=DjangoJSONEncoder),
            'title': f'Send {type_label}',
        }
        return render(request, 'admin/send_communication.html', context)

    def send_email_action(self, request, queryset):
        return self._send_communication_view(request, queryset, 'email')
    send_email_action.short_description = "Send Email"

    def send_sms_action(self, request, queryset):
        return self._send_communication_view(request, queryset, 'sms')
    send_sms_action.short_description = "Send SMS"

    def send_whatsapp_action(self, request, queryset):
        return self._send_communication_view(request, queryset, 'whatsapp')
    send_whatsapp_action.short_description = "Send WhatsApp"

    def verify_users(self, request, queryset):
        updated = queryset.update(is_verified=True)
        self.message_user(request, f'{updated} users verified successfully.')
    verify_users.short_description = "Mark selected users as verified"
    
    def deactivate_users(self, request, queryset):
        updated = queryset.update(is_active=False)
        self.message_user(request, f'{updated} users deactivated.')
    deactivate_users.short_description = "Deactivate selected users"
    
    def make_staff(self, request, queryset):
        updated = queryset.update(role=User.Role.CUSTOMER_SUPPORT, is_staff=True)
        self.message_user(request, f'{updated} users converted to staff.')
    make_staff.short_description = "Convert to Customer Support Staff"
    
    def make_customer(self, request, queryset):
        updated = queryset.update(role=User.Role.CUSTOMER, is_staff=False)
        self.message_user(request, f'{updated} users converted to customers.')
    make_customer.short_description = "Convert to Customer"

    def change_password_link(self, obj):
        if not obj or not obj.pk:
            return ''
        url = reverse('admin:accounts_user_set_password', args=[obj.pk])
        return format_html('<a class="button" href="{}">Change password</a>', url)
    change_password_link.short_description = 'Password'

    def get_urls(self):
        urls = super().get_urls()
        extra_urls = [
            path(
                '<path:object_id>/set-password/',
                self.admin_site.admin_view(self.user_change_password),
                name='accounts_user_set_password',
            ),
        ]
        return extra_urls + urls

    def user_change_password(self, request, object_id, *args, **kwargs):
        user = self.get_object(request, object_id)
        if user is None:
            return redirect('admin:accounts_user_changelist')
        if request.method == 'POST':
            form = AdminPasswordChangeForm(user, request.POST)
            if form.is_valid():
                form.save()
                messages.success(request, 'Password changed successfully.')
                return redirect('admin:accounts_user_change', object_id=user.pk)
        else:
            form = AdminPasswordChangeForm(user)
        context = {
            **self.admin_site.each_context(request),
            'title': 'Change password',
            'opts': self.model._meta,
            'original': user,
            'form': form,
            'is_popup': False,
            'save_as': False,
            'has_view_permission': self.has_view_permission(request, user),
            'has_change_permission': self.has_change_permission(request, user),
            'has_add_permission': self.has_add_permission(request),
            'has_delete_permission': self.has_delete_permission(request, user),
            'change': False,
        }
        return TemplateResponse(request, 'admin/auth/user/change_password.html', context)


@admin.register(Address)
class AddressAdmin(admin.ModelAdmin):
    """Address Management Admin"""
    
    list_display = (
        'user', 'full_name', 'city', 'state',
        'country', 'is_default', 'created_at'
    )
    list_filter = ('country', 'state', 'is_default')
    search_fields = ('user__email', 'full_name', 'city', 'pincode')
    ordering = ('-created_at',)
    
    fieldsets = (
        (_('User'), {'fields': ('user',)}),
        (_('Contact Information'), {'fields': ('full_name', 'phone')}),
        (_('Address'), {
            'fields': (
                'address_line1', 'address_line2', 'city',
                'state', 'country', 'pincode'
            )
        }),
        (_('Settings'), {'fields': ('is_default',)}),
    )


@admin.register(Wishlist)
class WishlistAdmin(admin.ModelAdmin):
    """Wishlist Management Admin"""
    
    list_display = ('user', 'product', 'added_at')
    list_filter = ('added_at',)
    search_fields = ('user__email', 'product__name')
    ordering = ('-added_at',)
    date_hierarchy = 'added_at'


# Unregister EmailAddress from admin as per user request
try:
    from allauth.account.models import EmailAddress
    if admin.site.is_registered(EmailAddress):
        admin.site.unregister(EmailAddress)
except ImportError:
    pass
