import json
from datetime import datetime, timedelta, date
from collections import defaultdict

from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, CreateView, UpdateView
from django.contrib import messages
from django.urls import reverse_lazy
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied
from django.http import JsonResponse
from django.core.paginator import Paginator
from django.views.decorators.http import require_POST, require_http_methods
from django import forms
from django.utils import timezone
from django.db.models import Q

from .models import Ticket, TicketComment, TicketAttachment
from .forms import TicketForm, TicketUpdateForm, TicketCommentForm, TicketAttachmentForm
from customers.models import Customer
from notifications.ticket_notifications import TicketNotificationService

User = get_user_model()

from accounts.permissions import (
    can_assign_tickets,
    EmployeeRequiredMixin,
    CustomerRequiredMixin,
    permission_required,
    any_permission_required,
    has_permission,
    get_user_permissions
)


@login_required
def ticket_list(request):
    """List all tickets with filters"""
    # Filter tickets based on user role and permissions
    if request.user.is_superuser:
        # Superusers see all tickets
        tickets = Ticket.objects.all()
    elif request.user.is_staff:
        # Staff see all tickets they can access
        tickets = Ticket.objects.all()
    else:
        # Non-staff users see only tickets they created or are assigned to
        tickets = Ticket.objects.filter(
            Q(created_by=request.user) |
            Q(assigned_to=request.user) |
            (Q(assigned_employee__user=request.user) if hasattr(request.user, 'employee_profile') else Q())
        )

    tickets = tickets.select_related(
        'customer', 'assigned_to', 'assigned_employee'
    )

    # Apply filters
    filter_type = request.GET.get('filter', '').strip()
    search_query = request.GET.get('search', '').strip()
    sort_column = request.GET.get('sort', '').strip()
    sort_order = request.GET.get('order', 'asc').strip()

    # Legacy support for status filter
    status_filter = request.GET.get('status', '').strip()
    if status_filter and not filter_type:
        filter_type = status_filter

    # Apply filter type
    if filter_type == 'active':
        tickets = tickets.filter(status__in=['open', 'in_progress'])
    elif filter_type == 'resolved':
        tickets = tickets.filter(status__in=['resolved', 'closed'])
    elif filter_type == 'urgent':
        tickets = tickets.filter(priority='urgent', status__in=['open', 'in_progress'])
    # 'all' or empty means no status filter

    # Apply search
    if search_query:
        # Search across ticket subject, customer name, assigned users, and ticket ID
        search_q = Q(title__icontains=search_query) | Q(ticket_id__icontains=search_query)

        # Search customer
        if hasattr(tickets.model, 'customer'):
            search_q |= Q(customer__full_name__icontains=search_query)
            search_q |= Q(customer__phone__icontains=search_query)
            search_q |= Q(customer__customer_id__icontains=search_query)

        # Search assigned users
        search_q |= Q(assigned_to__username__icontains=search_query)
        search_q |= Q(assigned_to__first_name__icontains=search_query)
        search_q |= Q(assigned_to__last_name__icontains=search_query)
        search_q |= Q(assigned_employee__full_name__icontains=search_query)
        search_q |= Q(assigned_employee__employee_id__icontains=search_query)

        tickets = tickets.filter(search_q)

    # Apply sorting
    sort_field = '-created_at'  # default
    if sort_column:
        sort_fields = {
            'ticket_id': 'ticket_id',
            'customer': 'customer__full_name',
            'title': 'title',
            'priority': 'priority',
            'status': 'status',
            'assigned_to': 'assigned_employee__full_name',
            'created_at': 'created_at'
        }

        if sort_column in sort_fields:
            field = sort_fields[sort_column]
            if sort_order == 'desc':
                field = '-' + field
            sort_field = field

    tickets = tickets.order_by(sort_field)

    # Paginate results
    paginator = Paginator(tickets, 25)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    # Get filter options
    from hr.models import Employee
    from django.contrib.auth import get_user_model
    User = get_user_model()

    employees = Employee.objects.filter(employment_status='active').order_by('employee_id')
    users = User.objects.filter(is_staff=True, is_active=True).order_by('username')

    # Statistics
    total_tickets = tickets.count()
    open_tickets = tickets.filter(status__in=['open', 'in_progress']).count()
    resolved_tickets = tickets.filter(status='resolved').count()
    urgent_tickets = tickets.filter(priority='urgent', status__in=['open', 'in_progress']).count()

    context = {
        'page_obj': page_obj,
        'status_filter': filter_type,
        'search_query': search_query,
        'sort_column': sort_column,
        'sort_order': sort_order,
        'total_tickets': total_tickets,
        'open_tickets': open_tickets,
        'resolved_tickets': resolved_tickets,
        'urgent_tickets': urgent_tickets,
    }

    return render(request, 'tickets/ticket_list.html', context)


@login_required
@permission_required('view_calendar')
def scheduled_tickets(request):
    """View for staff to see scheduled tickets"""
    scheduled_tickets = Ticket.objects.filter(
        is_scheduled=True,
        scheduled_date__isnull=False
    ).order_by('scheduled_date')

    # Filter by date range if provided
    date_from = request.GET.get('date_from')
    date_to = request.GET.get('date_to')
    assigned_filter = request.GET.get('assigned_to')

    if date_from:
        try:
            date_from_parsed = datetime.strptime(date_from, '%Y-%m-%d').date()
            scheduled_tickets = scheduled_tickets.filter(scheduled_date__date__gte=date_from_parsed)
        except ValueError:
            pass

    if date_to:
        try:
            date_to_parsed = datetime.strptime(date_to, '%Y-%m-%d').date()
            scheduled_tickets = scheduled_tickets.filter(scheduled_date__date__lte=date_to_parsed)
        except ValueError:
            pass

    if assigned_filter:
        if assigned_filter.startswith('emp_'):
            # Employee assignment
            emp_id = assigned_filter[4:]
            scheduled_tickets = scheduled_tickets.filter(assigned_employee__employee_id=emp_id)
        else:
            # User assignment
            scheduled_tickets = scheduled_tickets.filter(assigned_to__username=assigned_filter)

    # Get assignment options for filter
    from hr.models import Employee
    employees = Employee.objects.filter(employment_status='active')
    users = User.objects.filter(is_staff=True)

    context = {
        'scheduled_tickets': scheduled_tickets,
        'employees': employees,
        'users': users,
        'date_from': date_from,
        'date_to': date_to,
        'assigned_filter': assigned_filter,
    }
    return render(request, 'tickets/scheduled_tickets.html', context)


@login_required
def my_tickets(request):
    """View for clients to see their own tickets"""
    if not hasattr(request.user, 'customer_profile'):
        messages.error(request, "You don't have a customer profile.")
        return redirect('dashboard')

    tickets = Ticket.objects.filter(
        customer=request.user.customer_profile
    ).order_by('-created_at')

    paginator = Paginator(tickets, 25)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    context = {
        'page_obj': page_obj,
    }
    return render(request, 'tickets/my_tickets.html', context)


@login_required
def create_ticket(request):
    """Create a new ticket"""
    if request.method == 'POST':
        form = TicketForm(request.POST)
        if form.is_valid():
            ticket = form.save()

            # Send notification if ticket is assigned during creation
            if ticket.assigned_employee or ticket.assigned_to:
                try:
                    notification_service = TicketNotificationService()
                    success = notification_service.send_ticket_assigned_notification(ticket)
                    if not success:
                        messages.warning(request, f'Ticket created but notification failed to send')
                except Exception as e:
                    messages.warning(request, f'Ticket created but notification error: {str(e)}')

            messages.success(request, f'Ticket {ticket.ticket_id} created successfully!')
            return redirect('tickets:ticket_detail', ticket_number=ticket.ticket_id)
    else:
        form = TicketForm()
        # If user is a customer, pre-select their profile
        if hasattr(request.user, 'customer_profile'):
            form.fields['customer'].initial = request.user.customer_profile
            form.fields['customer'].widget = forms.HiddenInput()

    context = {
        'form': form,
    }
    return render(request, 'tickets/create_ticket.html', context)


@login_required
def ticket_detail(request, ticket_number):
    """View ticket details"""
    ticket = get_object_or_404(Ticket, ticket_id=ticket_number)

    # Check permissions
    if not request.user.is_staff:
        if not hasattr(request.user, 'customer_profile') or ticket.customer != request.user.customer_profile:
            messages.error(request, "You don't have permission to view this ticket.")
            return redirect('tickets:my_tickets')

    comments = ticket.comments.all().order_by('created_at')
    attachments = ticket.attachments.all().order_by('-uploaded_at')

    # Filter internal comments for non-staff users
    if not request.user.is_staff:
        comments = comments.filter(is_internal=False)

    comment_form = TicketCommentForm()
    attachment_form = TicketAttachmentForm()

    context = {
        'ticket': ticket,
        'comments': comments,
        'attachments': attachments,
        'comment_form': comment_form,
        'attachment_form': attachment_form,
    }
    return render(request, 'tickets/ticket_detail.html', context)


@login_required
@any_permission_required('change_tickets', 'manage_tickets')
def ticket_edit(request, ticket_number):
    """Edit ticket (staff only)"""
    ticket = get_object_or_404(Ticket, ticket_id=ticket_number)
    old_status = ticket.status
    old_assigned_employee = ticket.assigned_employee
    old_assigned_to = ticket.assigned_to

    if request.method == 'POST':
        form = TicketUpdateForm(request.POST, instance=ticket)
        if form.is_valid():
            updated_ticket = form.save()

            # Initialize notification service
            notification_service = TicketNotificationService()

            # Check if assignment changed and send notification to new technician
            new_assigned_employee = updated_ticket.assigned_employee
            new_assigned_to = updated_ticket.assigned_to

            if (old_assigned_employee != new_assigned_employee or old_assigned_to != new_assigned_to) and (new_assigned_employee or new_assigned_to):
                try:
                    notification_service.send_ticket_assigned_notification(updated_ticket)
                except Exception as e:
                    messages.warning(request, f'Ticket updated but notification failed: {str(e)}')

            # Check if status changed and send notification to customer
            if old_status != updated_ticket.status and updated_ticket.customer:
                try:
                    if updated_ticket.status == 'resolved':
                        notification_service.send_service_completed_notification(updated_ticket)
                    elif updated_ticket.status == 'in_progress':
                        notification_service.send_technician_arriving_notification(updated_ticket)
                    elif updated_ticket.status == 'scheduled' and updated_ticket.scheduled_date:
                        notification_service.send_appointment_reminder(updated_ticket)
                except Exception as e:
                    messages.warning(request, f'Ticket updated but customer notification failed: {str(e)}')

            messages.success(request, f'Ticket {ticket.ticket_id} updated successfully!')
            return redirect('tickets:ticket_detail', ticket_number=ticket.ticket_id)
    else:
        form = TicketUpdateForm(instance=ticket)

    context = {
        'form': form,
        'ticket': ticket,
    }
    return render(request, 'tickets/ticket_edit.html', context)


@login_required
@require_POST
def add_comment(request, ticket_number):
    """Add comment to ticket"""
    ticket = get_object_or_404(Ticket, ticket_id=ticket_number)
    ticket_id = ticket.id  # Get the ticket ID

    # Check permissions
    if not request.user.is_staff:
        if not hasattr(request.user, 'customer_profile') or ticket.customer != request.user.customer_profile:
            messages.error(request, "You don't have permission to comment on this ticket.")
            return redirect('tickets:my_tickets')

    form = TicketCommentForm(request.POST)
    if form.is_valid():
        comment = form.save(commit=False)
        comment.ticket = ticket
        comment.user = request.user

        # Only staff can create internal comments
        if not request.user.is_staff:
            comment.is_internal = False

        comment.save()
        messages.success(request, 'Comment added successfully!')
    else:
        messages.error(request, 'Error adding comment. Please check your input.')

    return redirect('tickets:ticket_detail', ticket_number=ticket.ticket_id)


@login_required
@require_POST
def add_attachment(request, ticket_number):
    """Add attachment to ticket"""
    ticket = get_object_or_404(Ticket, ticket_id=ticket_number)
    ticket_id = ticket.id

    # Check permissions
    if not request.user.is_staff:
        if not hasattr(request.user, 'customer_profile') or ticket.customer != request.user.customer_profile:
            messages.error(request, "You don't have permission to add attachments to this ticket.")
            return redirect('tickets:my_tickets')

    form = TicketAttachmentForm(request.POST, request.FILES)
    if form.is_valid():
        attachment = form.save(commit=False)
        attachment.ticket = ticket
        attachment.uploaded_by = request.user
        attachment.save()
        messages.success(request, 'Attachment uploaded successfully!')
    else:
        for field, errors in form.errors.items():
            for error in errors:
                messages.error(request, f'{field}: {error}')

    return redirect('tickets:ticket_detail', ticket_number=ticket.ticket_id)


@login_required
@any_permission_required('view_calendar', 'view_tickets')
def calendar_view(request):
    """Display calendar view with scheduled tickets"""
    # Get filter parameters
    technician_filter = request.GET.get('technician')
    month = request.GET.get('month')
    year = request.GET.get('year')

    # Default to current month if not specified
    if not month or not year:
        today = date.today()
        month = today.month
        year = today.year
    else:
        month = int(month)
        year = int(year)

    # Calculate date range for the month
    start_date = date(year, month, 1)
    if month == 12:
        end_date = date(year + 1, 1, 1) - timedelta(days=1)
    else:
        end_date = date(year, month + 1, 1) - timedelta(days=1)

    # Base query for scheduled tickets
    tickets = Ticket.objects.filter(
        is_scheduled=True,
        scheduled_date__date__gte=start_date,
        scheduled_date__date__lte=end_date
    ).order_by('scheduled_date')

    # Apply technician filter
    if technician_filter:
        if technician_filter.startswith('emp_'):
            emp_id = technician_filter[4:]
            tickets = tickets.filter(assigned_employee__employee_id=emp_id)
        else:
            tickets = tickets.filter(assigned_to__username=technician_filter)

    # Get technicians for filter
    from hr.models import Employee
    employees = Employee.objects.filter(employment_status='active')
    users = User.objects.filter(is_staff=True)

    # Group tickets by date
    calendar_data = defaultdict(list)
    for ticket in tickets:
        ticket_date = ticket.scheduled_date.date()
        calendar_data[ticket_date].append({
            'id': ticket.id,
            'ticket_id': ticket.ticket_id,
            'title': ticket.title,
            'customer': ticket.customer_name,
            'scheduled_time': ticket.scheduled_date.strftime('%H:%M'),
            'end_time': ticket.scheduled_end_time.strftime('%H:%M') if ticket.scheduled_end_time else None,
            'duration': str(ticket.estimated_duration) if ticket.estimated_duration else 'Not set',
            'assigned_person': ticket.assigned_person,
            'priority': ticket.priority,
            'status': ticket.status,
            'category': ticket.category,
        })

    # Generate calendar structure
    import calendar
    cal = calendar.monthcalendar(year, month)

    context = {
        'calendar_data': dict(calendar_data),
        'calendar_structure': cal,
        'current_month': month,
        'current_year': year,
        'month_name': calendar.month_name[month],
        'technician_filter': technician_filter,
        'employees': employees,
        'users': users,
        'prev_month': month - 1 if month > 1 else 12,
        'prev_year': year if month > 1 else year - 1,
        'next_month': month + 1 if month < 12 else 1,
        'next_year': year if month < 12 else year + 1,
    }

    return render(request, 'tickets/calendar_view.html', context)


@login_required
@any_permission_required('view_tickets', 'manage_schedules')
def my_schedule(request):
    """View for technicians to see their own schedule"""
    # Get employee profile if exists
    employee = None
    if hasattr(request.user, 'employee_profile'):
        employee = request.user.employee_profile

    # Get tickets assigned to this user/employee - only show active and scheduled tickets
    base_query = Q(assigned_to=request.user)
    if employee:
        base_query |= Q(assigned_employee=employee)

    tickets = Ticket.objects.filter(
        base_query,
        is_scheduled=True,
        scheduled_date__isnull=False,
        status__in=['open', 'in_progress', 'scheduled']  # Only show active tickets
    ).order_by('scheduled_date')

    # Filter by date range if provided
    date_from = request.GET.get('date_from')
    date_to = request.GET.get('date_to')

    if date_from:
        try:
            date_from_parsed = datetime.strptime(date_from, '%Y-%m-%d').date()
            tickets = tickets.filter(scheduled_date__date__gte=date_from_parsed)
        except ValueError:
            pass

    if date_to:
        try:
            date_to_parsed = datetime.strptime(date_to, '%Y-%m-%d').date()
            tickets = tickets.filter(scheduled_date__date__lte=date_to_parsed)
        except ValueError:
            pass

    context = {
        'tickets': tickets,
        'employee': employee,
        'date_from': date_from,
        'date_to': date_to,
    }

    return render(request, 'tickets/my_schedule.html', context)


@login_required
@require_http_methods(["POST"])
@permission_required('assign_tickets')
def reassign_ticket(request, ticket_id):
    """Reassign ticket to different technician"""
    ticket = get_object_or_404(Ticket, id=ticket_id)
    new_assignee = request.POST.get('new_assignee')

    if not new_assignee:
        return JsonResponse({'success': False, 'error': 'No assignee selected'})

    try:
        if new_assignee.startswith('emp_'):
            # Employee assignment
            from hr.models import Employee
            emp_id = new_assignee[4:]
            employee = Employee.objects.get(employee_id=emp_id)
            ticket.assigned_employee = employee
            ticket.assigned_to = employee.user if employee.user else None
        else:
            # User assignment
            user = User.objects.get(username=new_assignee)
            ticket.assigned_to = user
            ticket.assigned_employee = getattr(user, 'employee_profile', None)

        ticket.save()

        # Send notification to newly assigned technician
        try:
            notification_service = TicketNotificationService()
            success = notification_service.send_ticket_assigned_notification(ticket)
            if not success:
                print(f"Failed to send notification for ticket {ticket.ticket_id}")
        except Exception as e:
            print(f"Error sending notification for ticket {ticket.ticket_id}: {str(e)}")
            # Don't fail the reassignment if notification fails
            pass

        # Add comment about reassignment
        TicketComment.objects.create(
            ticket=ticket,
            user=request.user,
            comment=f"Ticket reassigned to {ticket.assigned_person}",
            is_internal=True
        )

        return JsonResponse({
            'success': True,
            'message': f'Ticket reassigned to {ticket.assigned_person}'
        })

    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
@require_http_methods(["POST"])
@any_permission_required('change_tickets', 'manage_tickets')
def update_ticket_time(request, ticket_id):
    """Update ticket actual start/end times"""
    ticket = get_object_or_404(Ticket, id=ticket_id)
    action = request.POST.get('action')

    try:
        if action == 'start':
            ticket.work_started_at = timezone.now()
            ticket.status = 'in_progress'
            message = 'Work started'

            # Send notification to customer that technician is arriving
            if ticket.customer:
                try:
                    notification_service = TicketNotificationService()
                    notification_service.send_technician_arriving_notification(ticket)
                except Exception as e:
                    # Don't fail the update if notification fails
                    pass

        elif action == 'complete':
            if not ticket.work_started_at:
                ticket.work_started_at = timezone.now()
            ticket.completed_at = timezone.now()
            ticket.status = 'resolved'

            # Calculate actual duration
            if ticket.work_started_at:
                ticket.actual_duration = ticket.completed_at - ticket.work_started_at

            message = 'Work completed'

            # Send completion notification to customer
            if ticket.customer:
                try:
                    notification_service = TicketNotificationService()
                    notification_service.send_service_completed_notification(ticket)
                except Exception as e:
                    # Don't fail the update if notification fails
                    pass
        else:
            return JsonResponse({'success': False, 'error': 'Invalid action'})

        ticket.save()

        # Add comment
        TicketComment.objects.create(
            ticket=ticket,
            user=request.user,
            comment=message,
            is_internal=True
        )

        return JsonResponse({'success': True, 'message': message})

    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
@permission_required('manage_schedules')
def schedule_template_list(request):
    """List all schedule templates"""
    # For now, return empty templates until ScheduleTemplate model is created
    templates = []

    context = {
        'templates': templates,
    }
    return render(request, 'tickets/schedule_template_list.html', context)


@login_required
@permission_required('manage_schedules')
def create_schedule_template(request):
    """Create a new schedule template"""
    # Placeholder view - will be implemented when ScheduleTemplate model is created
    messages.info(request, "Schedule template creation is not yet implemented.")
    return redirect('tickets:schedule_template_list')


@login_required
@permission_required('manage_schedules')
def edit_schedule_template(request, template_id):
    """Edit an existing schedule template"""
    # Placeholder view - will be implemented when ScheduleTemplate model is created
    messages.info(request, "Schedule template editing is not yet implemented.")
    return redirect('tickets:schedule_template_list')


@login_required
@permission_required('manage_schedules')
def use_schedule_template(request, template_id):
    """Use a schedule template to create tickets"""
    # Placeholder view - will be implemented when ScheduleTemplate model is created
    messages.info(request, "Schedule template usage is not yet implemented.")
    return redirect('tickets:schedule_template_list')


@login_required
@require_http_methods(["POST"])
@permission_required('manage_schedules')
def delete_schedule_template(request, template_id):
    """Delete a schedule template"""
    # Placeholder view - will be implemented when ScheduleTemplate model is created
    return JsonResponse({'success': False, 'error': 'Schedule template deletion is not yet implemented'})


@login_required
@permission_required('view_calendar')
def day_timeline(request):
    """Get timeline data for a specific day"""
    date_str = request.GET.get('date')
    technician_filter = request.GET.get('technician')

    if not date_str:
        return JsonResponse({'error': 'Date parameter required'}, status=400)

    try:
        date_obj = datetime.strptime(date_str, '%Y-%m-%d').date()
    except ValueError:
        return JsonResponse({'error': 'Invalid date format'}, status=400)

    # Get tickets for the specified date
    tickets = Ticket.objects.filter(
        is_scheduled=True,
        scheduled_date__date=date_obj
    ).order_by('scheduled_date')

    # Apply technician filter
    if technician_filter:
        if technician_filter.startswith('emp_'):
            emp_id = technician_filter[4:]
            tickets = tickets.filter(assigned_employee__employee_id=emp_id)
        else:
            tickets = tickets.filter(assigned_to__username=technician_filter)

    # Group tickets by hour
    timeline_data = {}
    for ticket in tickets:
        hour = ticket.scheduled_date.hour
        hour_key = str(hour).zfill(2)

        if hour_key not in timeline_data:
            timeline_data[hour_key] = []

        duration_str = ""
        if ticket.estimated_duration:
            total_seconds = int(ticket.estimated_duration.total_seconds())
            hours = total_seconds // 3600
            minutes = (total_seconds % 3600) // 60
            if hours > 0:
                duration_str = f"{hours}h {minutes}m"
            else:
                duration_str = f"{minutes}m"

        timeline_data[hour_key].append({
            'id': ticket.id,
            'ticket_id': ticket.ticket_id,
            'title': ticket.title,
            'assigned_person': ticket.assigned_person,
            'priority': ticket.priority,
            'status': ticket.status,
            'duration': duration_str,
            'customer': ticket.customer_name,
        })

    return JsonResponse({'timeline': timeline_data})


@login_required
@permission_required('view_calendar')
def unscheduled_tickets(request):
    """Get list of unscheduled tickets"""
    tickets = Ticket.objects.filter(
        Q(is_scheduled=False) | Q(scheduled_date__isnull=True),
        status__in=['open', 'in_progress']
    ).order_by('-created_at')

    ticket_data = []
    for ticket in tickets:
        ticket_data.append({
            'id': ticket.id,
            'ticket_id': ticket.ticket_id,
            'title': ticket.title,
            'customer': ticket.customer_name,
            'priority': ticket.priority,
            'status': ticket.status,
        })

    return JsonResponse({'tickets': ticket_data})


@login_required
@require_http_methods(["POST"])
@permission_required('manage_schedules')
def schedule_existing_ticket(request):
    """Schedule an existing ticket"""
    ticket_id = request.POST.get('ticket_id')
    scheduled_date = request.POST.get('scheduled_date')
    assigned_technician = request.POST.get('assigned_technician')
    estimated_duration = request.POST.get('estimated_duration')

    if not all([ticket_id, scheduled_date, assigned_technician]):
        return JsonResponse({'success': False, 'error': 'Missing required fields'})

    try:
        ticket = Ticket.objects.get(id=ticket_id)
        old_assigned_employee = ticket.assigned_employee
        old_assigned_to = ticket.assigned_to

        # Parse scheduled date
        scheduled_datetime = datetime.strptime(scheduled_date, '%Y-%m-%dT%H:%M')

        # Update ticket
        ticket.scheduled_date = scheduled_datetime
        ticket.is_scheduled = True
        ticket.status = 'scheduled'

        # Set estimated duration
        if estimated_duration:
            duration_hours = float(estimated_duration)
            ticket.estimated_duration = timedelta(hours=duration_hours)

        # Assign technician
        if assigned_technician.startswith('emp_'):
            from hr.models import Employee
            emp_id = assigned_technician[4:]
            employee = Employee.objects.get(employee_id=emp_id)
            ticket.assigned_employee = employee
            ticket.assigned_to = employee.user if employee.user else None
        else:
            user = User.objects.get(username=assigned_technician)
            ticket.assigned_to = user
            ticket.assigned_employee = getattr(user, 'employee_profile', None)

        ticket.save()

        # Send notifications
        try:
            notification_service = TicketNotificationService()

            # Send notification to technician if newly assigned
            if (old_assigned_employee != ticket.assigned_employee or old_assigned_to != ticket.assigned_to):
                success = notification_service.send_ticket_assigned_notification(ticket)
                if not success:
                    print(f"Failed to send technician notification for ticket {ticket.ticket_id}")

            # Send appointment confirmation to customer
            if ticket.customer:
                success = notification_service.send_appointment_confirmation(ticket)
                if not success:
                    print(f"Failed to send customer notification for ticket {ticket.ticket_id}")

        except Exception as e:
            print(f"Error sending notifications for ticket {ticket.ticket_id}: {str(e)}")
            # Don't fail the scheduling if notification fails
            pass

        # Add comment about scheduling
        TicketComment.objects.create(
            ticket=ticket,
            user=request.user,
            comment=f"Ticket scheduled for {scheduled_datetime.strftime('%Y-%m-%d %H:%M')} and assigned to {ticket.assigned_person}",
            is_internal=True
        )

        return JsonResponse({'success': True, 'message': 'Ticket scheduled successfully'})

    except Ticket.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Ticket not found'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
@require_http_methods(["POST"])
@permission_required('manage_schedules')
def reschedule_ticket(request, ticket_id):
    """Reschedule an existing ticket to a new time"""
    new_datetime_str = request.POST.get('new_datetime')

    if not new_datetime_str:
        return JsonResponse({'success': False, 'error': 'New datetime is required'})

    try:
        ticket = Ticket.objects.get(id=ticket_id)

        # Parse the new datetime
        new_datetime = datetime.strptime(new_datetime_str, '%Y-%m-%dT%H:%M')

        # Store old datetime for comment
        old_datetime = ticket.scheduled_date

        # Update the ticket
        ticket.scheduled_date = new_datetime
        ticket.is_scheduled = True
        ticket.save()

        # Add comment about rescheduling
        old_time_str = old_datetime.strftime('%Y-%m-%d %H:%M') if old_datetime else 'Unscheduled'
        new_time_str = new_datetime.strftime('%Y-%m-%d %H:%M')

        TicketComment.objects.create(
            ticket=ticket,
            user=request.user,
            comment=f"Ticket rescheduled from {old_time_str} to {new_time_str}",
            is_internal=True
        )

        return JsonResponse({
            'success': True,
            'message': f'Ticket rescheduled to {new_time_str}',
            'new_datetime': new_time_str
        })

    except Ticket.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Ticket not found'})
    except ValueError as e:
        return JsonResponse({'success': False, 'error': 'Invalid datetime format'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
@require_http_methods(["POST"])
@any_permission_required('change_tickets', 'manage_tickets')
def change_ticket_status(request, ticket_number):
    """Change ticket status via AJAX"""
    import json

    try:
        # Parse JSON body
        data = json.loads(request.body)
        new_status = data.get('status')

        if not new_status:
            return JsonResponse({'success': False, 'error': 'Status is required'})

        # Validate status
        valid_statuses = [choice[0] for choice in Ticket.STATUS_CHOICES]
        if new_status not in valid_statuses:
            return JsonResponse({'success': False, 'error': 'Invalid status'})

        ticket = Ticket.objects.get(ticket_id=ticket_number)
        old_status = ticket.status

        # Update ticket status
        ticket.status = new_status

        # Handle special status changes
        if new_status == 'resolved' and old_status != 'resolved':
            ticket.resolved_at = timezone.now()
            # Send completion notification to customer
            if ticket.customer:
                try:
                    notification_service = TicketNotificationService()
                    notification_service.send_service_completed_notification(ticket)
                except Exception as e:
                    # Don't fail the update if notification fails
                    pass

        elif new_status == 'in_progress' and old_status != 'in_progress':
            if not ticket.work_started_at:
                ticket.work_started_at = timezone.now()
            # Send notification to customer that technician is working
            if ticket.customer:
                try:
                    notification_service = TicketNotificationService()
                    notification_service.send_technician_arriving_notification(ticket)
                except Exception as e:
                    # Don't fail the update if notification fails
                    pass

        ticket.save()

        # Add comment about status change
        status_display = dict(Ticket.STATUS_CHOICES).get(new_status, new_status)
        old_status_display = dict(Ticket.STATUS_CHOICES).get(old_status, old_status)

        TicketComment.objects.create(
            ticket=ticket,
            user=request.user,
            comment=f"Status changed from {old_status_display} to {status_display}",
            is_internal=True
        )

        return JsonResponse({
            'success': True,
            'message': f'Ticket status changed to {status_display}',
            'new_status': new_status
        })

    except Ticket.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Ticket not found'})
    except json.JSONDecodeError:
        return JsonResponse({'success': False, 'error': 'Invalid JSON data'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})