from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.http import require_POST

from chat.models import UserProfile, Channel, Message, DirectMessage
from chat.forms import RegisterForm, ProfileForm, ChannelForm, MessageFileForm
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync


def _broadcast_message(group_name, message_type, msg, request_user):
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        group_name,
        {
            'type': message_type,
            'message': msg.content,
            'sender': request_user.username,
            'sender_id': request_user.id,
            'message_id': msg.id,
            'timestamp': msg.timestamp.strftime('%H:%M'),
            'avatar': request_user.profile.avatar.url if request_user.profile.avatar else None,
            'role': request_user.profile.role,
            'file_url': msg.file.url if msg.file else None,
            'file_name': msg.file.name if msg.file else None,
        }
    )

def register_view(request):
    form = RegisterForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        user = User.objects.create_user(
            username=form.cleaned_data['username'],
            email=form.cleaned_data['email'],
            password=form.cleaned_data['password'],
        )
        UserProfile.objects.create(user=user)
        login(request, user)
        return redirect('home')
    return render(request, 'chat/register.html', {'form': form})


def login_view(request):
    error = None
    if request.method == 'POST':
        user = authenticate(request,
                            username=request.POST.get('username'),
                            password=request.POST.get('password'))
        if user:
            login(request, user)
            return redirect('home')
        error = 'Invalid credentials.'
    return render(request, 'chat/login.html', {'error': error})


def logout_view(request):
    logout(request)
    return redirect('login')


@login_required
def home_view(request):
    channels = Channel.objects.all().prefetch_related('members')
    users = User.objects.exclude(id=request.user.id).select_related('profile')
    return render(request, 'chat/home.html', {'channels': channels, 'users': users})


@login_required
def channel_view(request, channel_id):
    channel = get_object_or_404(Channel, id=channel_id)
    # Join if not member
    if request.user not in channel.members.all():
        channel.members.add(request.user)

    # File upload via POST
    if request.method == 'POST':
        f = request.FILES.get('file')
        if f:
            msg = Message.objects.create(
                channel=channel,
                sender=request.user,
                content=request.POST.get('content', ''),
                file=f,
            )
            _broadcast_message(f'channel_{channel.id}', 'chat_message', msg, request.user)
        return redirect('channel', channel_id=channel_id)

    messages_qs = channel.messages.filter(deleted=False).select_related('sender', 'sender__profile')
    return render(request, 'chat/channel.html', {
        'channel': channel,
        'messages': messages_qs,
        'all_channels': Channel.objects.all(),
    })


@login_required
def create_channel_view(request):
    profile = request.user.profile
    if not profile.is_moderator():
        messages.error(request, 'No permission.')
        return redirect('home')
    form = ChannelForm(request.POST or None)
    if form.is_valid():
        ch = form.save(commit=False)
        ch.created_by = request.user
        ch.save()
        ch.members.add(request.user)
        return redirect('channel', channel_id=ch.id)
    return render(request, 'chat/create_channel.html', {'form': form})


@login_required
def delete_channel_view(request, channel_id):
    channel = get_object_or_404(Channel, id=channel_id)
    if request.user.profile.is_admin():
        channel.delete()
    return redirect('home')


@login_required
def dm_view(request, username):
    other = get_object_or_404(User, username=username)
    if request.method == 'POST':
        f = request.FILES.get('file')
        if f:
            msg = DirectMessage.objects.create(
                sender=request.user,
                receiver=other,
                content=request.POST.get('content', ''),
                file=f,
            )
            ids = sorted([request.user.id, other.id])
            _broadcast_message(f'dm_{ids[0]}_{ids[1]}', 'dm_message', msg, request.user)
        return redirect('dm', username=username)

    dms = DirectMessage.objects.filter(
        sender__in=[request.user, other],
        receiver__in=[request.user, other],
    ).select_related('sender', 'sender__profile').order_by('timestamp')

    return render(request, 'chat/dm.html', {
        'other': other,
        'messages': dms,
        'all_users': User.objects.exclude(id=request.user.id).select_related('profile'),
    })


@login_required
def profile_view(request):
    profile = request.user.profile
    form = ProfileForm(request.POST or None, request.FILES or None, instance=profile)
    if form.is_valid():
        form.save()
        messages.success(request, 'Profile updated.')
        return redirect('profile')
    return render(request, 'chat/profile.html', {'form': form})


def _handle_admin_action(request, action, target, role):
    if action == 'set_role' and role:
        target.profile.role = role
        target.profile.save()
        messages.success(request, f'Role updated for {target.username}.')
    elif action == 'block':
        request.user.profile.blocked_users.add(target)
        messages.success(request, f'{target.username} blocked.')
    elif action == 'unblock':
        request.user.profile.blocked_users.remove(target)
        messages.success(request, f'{target.username} unblocked.')


@login_required
def admin_panel_view(request):
    if not request.user.profile.is_admin():
        messages.error(request, 'No permission.')
        return redirect('home')

    users = User.objects.all().select_related('profile').exclude(id=request.user.id)

    if request.method == 'POST':
        user_id = request.POST.get('user_id')
        action = request.POST.get('action')
        role = request.POST.get('role')
        target = get_object_or_404(User, id=user_id)

        _handle_admin_action(request, action, target, role)

        return redirect('admin_panel')

    blocked_ids = list(request.user.profile.blocked_users.values_list('id', flat=True))
    return render(request, 'chat/admin_panel.html', {
        'users': users,
        'blocked_ids': blocked_ids,
    })


@login_required
def delete_message_view(request, message_id):
    msg = get_object_or_404(Message, id=message_id)
    if request.user.profile.is_moderator() or msg.sender == request.user:
        msg.deleted = True
        msg.save()
    return redirect('channel', channel_id=msg.channel_id)


@login_required
def block_user_view(request, user_id):
    if request.user.profile.is_moderator():
        target = get_object_or_404(User, id=user_id)
        request.user.profile.blocked_users.add(target)
    return redirect('home')


def handler404(request, exception):
    return render(request, 'chat/404.html', status=404)


def handler500(request):
    return render(request, 'chat/500.html', status=500)
