from django.shortcuts import render, redirect, get_object_or_404
from osinacore.models import *
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.urls import reverse
from django.http import HttpResponseRedirect
from datetime import date
from django.http import JsonResponse
from osinacore.decorators import *
from billing.models import *
from support.models import *
import os
from django.conf import settings
from django.core.files import File

@staff_login_required
def add_status_modal(request, *args, **kwargs):
    if request.method == 'POST':
        text = request.POST.get('text')
        date_time = datetime.now()

        try:
            staff_profile = StaffProfile.objects.get(user=request.user)
        except StaffProfile.DoesNotExist:
            # Handle the case where a StaffProfile does not exist for the user
            staff_profile = None

        status = Status(
            text=text,
            staff=staff_profile,
            date_time=date_time,
        )
        status.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')
    return render(request, 'add_templates/add-status-modal.html')


@staff_login_required
def add_customer(request):
    references = Reference.objects.all().order_by('-id')

    if request.method == 'POST':
        email = request.POST.get('email').lower()
        first_name = request.POST.get('first_name')
        last_name = request.POST.get('last_name')

        user = User.objects.create_user(
            username=email,
            email=email,
            password=request.POST.get('password2')
        )
        user.first_name = first_name.lower().capitalize()
        user.last_name = last_name.lower().capitalize()
        user.save()

        if request.POST.get('referenceid'):
            reference_id = request.POST.get('referenceid')
            reference = get_object_or_404(Reference, id=reference_id)
        else:
            reference = None

        CustomerProfile.objects.create(
            user=user,
            mobile_number=request.POST.get('mobile_number'),
            personal_website=request.POST.get('personal_website'),
            status=request.POST.get('status'),
            reference=reference,
        )
        return redirect('customers')

    context = {
        'references': references,

    }
    return render(request, 'add_templates/add-customer.html', context)


@staff_login_required
def add_business(request):
    customers = CustomerProfile.objects.all().order_by('-id')
    business_types = BusinessType.objects.all().order_by('-id')
    if request.method == 'POST':

        customer_id = request.POST.get('customer')
        customer = get_object_or_404(CustomerProfile, id=customer_id)

        name = request.POST.get('name')
        email = request.POST.get('email')
        financial_number = request.POST.get('financial_number')
        phone_number = request.POST.get('phone_number')
        vat = request.POST.get('vat')
        if vat:
            vat = True
        else:
            vat = False
        commercial_registration = request.POST.get('commercial_registration')
        website = request.POST.get('website')
        logo = request.FILES.get('logo')

        business_type_id = request.POST.get('type')
        business_type = get_object_or_404(BusinessType, id=business_type_id)

        business = Business(
            customer=customer,
            name=name,
            email=email,
            financial_number=financial_number,
            vat=vat,
            commercial_registration=commercial_registration,
            website=website,
            type=business_type,
            logo=logo,
            phone_number=phone_number,
        )
        business.save()

        return redirect('businesses')

    context = {
        'customers': customers,
        'business_types': business_types,
    }

    return render(request, 'add_templates/add-business.html', context)


@staff_login_required
def add_staff(request):
    jobpositions = JobPosition.objects.all().order_by('-id')
    if request.method == 'POST':
        email = request.POST.get('email').lower()
        first_name = request.POST.get('first_name')
        last_name = request.POST.get('last_name')
        username = f"{first_name.replace(' ', '').lower()}{last_name.replace(' ', '').lower()}"
        original_username = username
        counter = 1 

        while User.objects.filter(username=username).exists():
            username = f"{original_username.lower()}{counter}"
            counter += 1

        if request.POST.get('active'):
            active = True
        else:
            active = False

        user = User.objects.create_user(
            username=username,
            email=email,
            password=request.POST.get('password2'),
            is_staff=True,
            is_active=active
        )
        user.first_name = first_name.lower().capitalize()
        user.last_name = last_name.lower().capitalize()
        user.save()

        if request.POST.get('intern'):
            intern = True
        else:
            intern = False

        staff = StaffProfile.objects.create(
            user=user,
            image=request.FILES.get('image'),
            mobile_number=request.POST.get('mobile_number'),
            intern=intern,
        )

        position_ids = request.POST.getlist('position[]')
        start_dates = request.POST.getlist('start_date[]')
        end_dates = request.POST.getlist('end_date[]')

        for position_id, start_date, end_date in zip(position_ids, start_dates, end_dates):
            position = get_object_or_404(JobPosition, id=position_id)
            if end_date:
                end_date = end_date
            else:
                end_date = None
            StaffPosition.objects.create(
                staff = staff,
                position = position,
                start_date = start_date,
                end_date = end_date
            )


        return redirect('users')

    context = {
        'jobpositions': jobpositions,
    }
    return render(request, 'add_templates/add-staff.html', context)


@staff_login_required
def add_project(request):
    staffs = StaffProfile.objects.filter(active=True).order_by('user__first_name')
    project_types = ProjectType.objects.all()
    customers = CustomerProfile.objects.all().order_by('-id')
    if request.method == 'POST':
        name = request.POST.get('name')

        customerid = request.POST.get('customer')
        customer = get_object_or_404(CustomerProfile, id=customerid)

        managerid = request.POST.get('manager')
        manager = get_object_or_404(StaffProfile, id=managerid)

        project_type = request.POST.getlist('project_type')
        details = request.POST.get('details')
        membersids = request.POST.getlist('members')
        start_date = request.POST.get('start_date')
        end_date = request.POST.get('end_date')

        project = Project(
            name=name,
            customer=customer,
            manager=manager,
            details=details,
            start_date=start_date,
            end_date=end_date,
        )
        project.save()

        project.project_type.set(project_type)
        project.members.set(membersids)

        requirements = request.POST.getlist('requirements')
        for requirement_content in requirements:
            if requirement_content:
                requirement = ProjectRequirement(
                    content=requirement_content, project=project, added_by=request.user)
                requirement.save()

        return redirect('my-projects')

    context = {
        'staffs': staffs,
        'project_types': project_types,
        'customers': customers,

    }
    return render(request, 'add_templates/add-project.html', context)


@staff_login_required
def add_project_member_modal(request, project_id):
    project = get_object_or_404(Project, id=project_id)
    current_member_ids = list(project.members.values_list('id', flat=True))
    staffs = StaffProfile.objects.filter(active=True).order_by('user__first_name')
    if request.method == 'POST':
        membersids = request.POST.getlist('members')
        project.members.set(membersids)
        project.save()
        response = HttpResponse(
            '<script>window.top.location.reload();</script>')
        return response

    context = {
        'project': project,
        'staffs': staffs,
        'current_member_ids': current_member_ids,

    }
    return render(request, 'add_templates/add-project-member-modal.html', context)


@staff_login_required
def add_user_story_modal(request, project_id):
    project = get_object_or_404(Project, project_id=project_id)
    if request.method == 'POST':
        content = request.POST.get('content')

        story = ProjectRequirement(
            content=content,
            project=project,
            added_by=request.user,
        )
        story.save()
        # Reload the parent page using JavaScript
        response = HttpResponse(
            '<script>window.top.location.reload();</script>')
        return response

    context = {

        'project': project,

    }

    return render(request, 'add_templates/add-userstory-modal.html', context)


@staff_login_required
def add_file_modal(request, project_id):
    project = get_object_or_404(Project, project_id=project_id)
    if request.method == 'POST':
        project_file_album = ProjectFileAlbum.objects.create(
            project = project,
            name =  request.POST.get('name'),
        )
        for file in request.FILES.getlist('files'):
            ProjectFile.objects.create(
                album=project_file_album,
                file = file,
                date_added= datetime.now()
            )
        return HttpResponse('<script>window.top.location.reload();</script>')

    context = {
        'project': project

    }
    return render(request, 'add_templates/add-file-modal.html', context)


def add_credential_modal(request, project_id):
    project = get_object_or_404(Project, project_id=project_id)
    if request.method == 'POST':
        ProjectCredential.objects.create(
            identifier = request.POST.get('identifier'),
            password = request.POST.get('password'),
            description = request.POST.get('description'),
            date_added = datetime.now(),
            project = project
        )
        return HttpResponse('<script>window.top.location.reload();</script>')
    context = {
        'project': project,
    }
    return render(request, 'add_templates/add-credential-modal.html', context)





@staff_login_required
def add_task(request, project_id=None, requirement_id=None):
    project = None
    requirement = None
    epics_of_my_project = None
    projects = None

    # Case where user wants to add task from project page(Adding a task for a project)
    if project_id:
        project = get_object_or_404(Project, project_id=project_id)
        epics_of_my_project = Epic.objects.filter(project=project)
        if requirement_id:
            requirement = get_object_or_404(
                ProjectRequirement, id=requirement_id)

    # Case where user wants to add task from tasks page(No project specified)
    else:
        projects = Project.objects.all().order_by('-id')

    staffs = StaffProfile.objects.all().order_by('-id')

    if request.method == 'POST':
        name = request.POST.get('name')
        status = request.POST.get('status')
        extra = request.POST.get('extra')
        description = request.POST.get('description')
        start_date = request.POST.get('start_date')
        end_date = request.POST.get('end_date')

        if not project_id:
            project_id = request.POST.get('project')
            project = get_object_or_404(Project, id=project_id)

        epic_id = request.POST.get('epic')
        epic = get_object_or_404(Epic, id=epic_id)

        assigned_to_id = request.POST.get('assigned_to')
        assigned_to = get_object_or_404(StaffProfile, id=assigned_to_id)

        task = Task(
            name=name,
            status=status,
            project=project,
            epic=epic,
            extra=extra,
            description=description,
            start_date=start_date,
            end_date=end_date,
            assigned_to=assigned_to,
            requirement=requirement,

        )

        task.save()

        task_details_url = reverse('detailed-task', args=[task.task_id])
        if requirement:
            return redirect('detailed-project', project_id=project.project_id)
        else:
            return HttpResponseRedirect(task_details_url)

    context = {
        'project': project,
        'epics_of_my_project': epics_of_my_project,
        'staffs': staffs,
        'projects': projects,
        'requirement': requirement


    }
    return render(request, 'add_templates/add-task.html', context)


@staff_login_required
def add_point_modal(request, task_id):
    task = get_object_or_404(Task, task_id=task_id)
    if request.method == 'POST':
        text = request.POST.get('text')
        point = Point(
            text=text,
            task=task,
            status='Not Completed'
        )
        point.save()

        # Redirect back to the same page
        return redirect(request.META.get('HTTP_REFERER', ''))

    context = {
        'task': task,

    }
    return render(request, 'add_templates/add-point-modal.html', context)


@staff_login_required
def save_point_modal(request, task_id):
    task = get_object_or_404(Task, task_id=task_id)
    if request.method == 'POST':
        text = request.POST.get('text')
        point = Point(
            text=text,
            task=task,
            status='Not Completed'
        )
        point.save()
        return JsonResponse({'success': True, 'message': 'Point saved successfully.'})

    context = {
        'task': task,

    }
    return render(request, 'add_templates/add-point-modal.html', context)


@staff_login_required
def add_epic(request, project_id):
    project = get_object_or_404(Project, project_id=project_id)
    if request.method == 'POST':
        title = request.POST.get('title')
        status = request.POST.get('status')
        description = request.POST.get('description')

        project_id = request.POST.get('project')
        project = get_object_or_404(Project, id=project_id)

        start_date = request.POST.get('start_date')
        end_date = request.POST.get('end_date')

        epic = Epic(
            title=title,
            status=status,
            project=project,
            description=description,
            start_date=start_date,
            end_date=end_date
        )

        epic.save()

        redirect_url = reverse('detailed-project', args=[project.project_id])
        return redirect(redirect_url)

    context = {
        'project': project,
    }
    return render(request, 'add_templates/add-epic.html', context)


@staff_login_required
def add_note_modal(request, project_id=None):
    project = None
    # Case where user wants to add note for a project page(Adding a note for a project)
    if project_id:
        project = get_object_or_404(Project, project_id=project_id)
    else:
        project = None
    if request.method == 'POST':
        text = request.POST.get('note_text')
        color = request.POST.get('note_color')
        user = request.user
        date = timezone.now()

        note = Note(
            text=text,
            color=color,
            user=user,
            date=date,
            project=project,
        )
        note.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')
    context = {
        'project': project,
    }
    return render(request, 'add_templates/add-note-modal.html', context)


@staff_login_required
def add_daily_report(request):
    user = request.user
    today = date.today()
    statuses = Status.objects.filter(staff=user.staffprofile, date_time__date=today)
    if request.method == 'POST':
        text = request.POST.get('text')
        current_datetime = datetime.now()
        time = current_datetime.strftime("%I:%M %p")
        try:
            staff_profile = StaffProfile.objects.get(user=request.user)
        except StaffProfile.DoesNotExist:
            # Handle the case where a StaffProfile does not exist for the user
            staff_profile = None

        dailyreport = DailyReport(
            text=text,
            date=today,
            time=time,
            staff=staff_profile
        )
        dailyreport.save()

        return redirect('dailyreports')

    context = {
        'statuses': statuses,
    }
    return render(request, 'add_templates/add-daily-report.html', context)


@staff_login_required
def add_department_modal(request, *args, **kwargs):
    if request.method == 'POST':
        name = request.POST.get('name')
        department = Department(
            name=name,

        )
        department.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')
    return render(request, 'add_templates/add-department-modal.html')


@staff_login_required
def add_projecttype_modal(request, *args, **kwargs):
    departments = Department.objects.all().order_by('name')
    if request.method == 'POST':
        name = request.POST.get('name')
        projecttype = ProjectType(
            name=name,
            department=get_object_or_404(
                Department, id=request.POST.get('department'))

        )
        projecttype.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')
    context = {
        'departments': departments,
    }
    return render(request, 'add_templates/add-projecttype-modal.html', context)


@staff_login_required
def add_jobposition_modal(request):
    departments = Department.objects.all().order_by('name')
    if request.method == 'POST':
        name = request.POST.get('name')
        jobposition = JobPosition(
            name=name,
            department=get_object_or_404(
                Department, id=request.POST.get('department'))


        )
        jobposition.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')
    context = {
        'departments': departments,
    }
    return render(request, 'add_templates/add-jobposition-modal.html', context)


@staff_login_required
def add_businesstype_modal(request, *args, **kwargs):
    if request.method == 'POST':
        name = request.POST.get('name')

        businesstype = BusinessType(
            name=name,
        )
        businesstype.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')

    return render(request, 'add_templates/add-businesstype-modal.html')


@staff_login_required
def add_reference_modal(request, *args, **kwargs):
    if request.method == 'POST':
        name = request.POST.get('name')
        date = request.POST.get('date')

        reference = Reference(
            name=name,
            date=date,
        )
        reference.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')
    return render(request, 'add_templates/add-reference-modal.html')


@staff_login_required
def add_tag_modal(request, *args, **kwargs):
    if request.method == 'POST':
        name = request.POST.get('name')

        tag = Tag(
            name=name,
        )
        tag.save()

        # Reload the parent page
        return HttpResponse('<script>window.top.location.reload();</script>')
    return render(request, 'add_templates/add-tag-modal.html')


@staff_login_required
def add_reaction(request, status_id, emoji):
    status = get_object_or_404(Status, pk=status_id)
    user = request.user
    existing_reaction = Reaction.objects.filter(
        status=status, user=user).first()
    if existing_reaction:
        # If the user has already reacted, update the reaction
        existing_reaction.emoji = emoji
        existing_reaction.save()
        return JsonResponse({'message': 'Reaction updated successfully.'})
    else:
        # If the user hasn't reacted yet, create a new reaction
        new_reaction = Reaction.objects.create(
            status=status, emoji=emoji, user=user)
        return JsonResponse({'message': 'Reaction added successfully.'})


@staff_login_required
def add_ticket(request, customer_id=None, project_id=None):
    if customer_id:
        customer = get_object_or_404(CustomerProfile, id=customer_id)
    else:
        customer = None
    
    if project_id:
        project = get_object_or_404(Project, id=project_id)
        customer = project.customer
    else:
        project=None

    customers = CustomerProfile.objects.all().order_by('-id')
    customer_orders = Order.objects.filter(customer=customer)
    customer_orders_with_last_status = customer_orders.annotate(max_status_date=Max('orderstatus__date'))
    customer_orders_completed = customer_orders_with_last_status.filter(orderstatus__status='Completed', orderstatus__date=F('max_status_date'))
    customer_products = OrderItem.objects.filter(active__in=[True, None], item__type='Product', order__customer=customer, order__in=customer_orders_completed)
    customer_projects = Project.objects.filter(customer=customer)
    all_departments = Department.objects.all().order_by('name')
    support_department = get_object_or_404(Department, name='Support')

    if request.method == 'POST':
        if not project:
            project = None

        product = None
        regarding = 'General/Account/Billing'

        if not project:
            if request.POST.get('project'):
                project = get_object_or_404(Project, id=request.POST.get('project'))
                regarding = 'Project/Product'

        elif request.POST.get('product'):
            product = get_object_or_404(Item, id=request.POST.get('product'))
            regarding = 'Project/Product'

        if request.POST.get('department'):
            department = get_object_or_404(Department, id=request.POST.get('department'))
        else:
            department = support_department

        ticket = Ticket(
            customer=customer,
            title=request.POST.get('title'),
            description=request.POST.get('description'),
            regarding=regarding,
            project=project,
            product=product,
            opened_by=request.user,
            opened_date=datetime.now()
        )
        ticket.save()

        ticket_status = TicketStatus(
            ticket = ticket,
            status = 'Open',
            added_by = request.user,
            date_added = datetime.now()
        )
        ticket_status.save()


        ticketdepartment = TicketDepartment(
            ticket=ticket,
            department=department,
            date_added = datetime.now()
        )
        ticketdepartment.save()
        

        file_paths = request.POST.getlist('filePath') 

        for file_path in file_paths:
            ticket_attachment = TicketAttachment(
                ticket=ticket,
                file_path=file_path  
            )
            ticket_attachment.save()

        return redirect('ticketroom', ticket_number=ticket.ticket_number)

    context = {
        'customer_products': customer_products,
        'customer_projects': customer_projects,
        'customer': customer,
        'all_departments': all_departments,
        'project' : project,
        'customers' : customers,
    }

    return render(request, 'add_templates/add-ticket.html', context)


def fetch_customer_information(request, customer_id):
    customer = get_object_or_404(CustomerProfile, id=customer_id)
    customer_orders = Order.objects.filter(customer=customer)
    customer_orders_with_last_status = customer_orders.annotate(max_status_date=Max('orderstatus__date'))
    customer_orders_completed = customer_orders_with_last_status.filter(orderstatus__status='Completed', orderstatus__date=F('max_status_date'))
    customer_products = OrderItem.objects.filter(active__in=[True, None], item__type='Product', order__customer=customer, order__in=customer_orders_completed)
    customer_projects = Project.objects.filter(customer=customer)


    response_data = {
        'orders': list(customer_orders_completed.values()), 
        'products': list(customer_products.values()),
        'projects': list(customer_projects.values()),
    }

    return JsonResponse(response_data, safe=False)
    


def upload_file(request):
    if 'file' not in request.FILES or 'filename' not in request.POST:
        return JsonResponse({'data': 'Invalid Request'})

    file = request.FILES['file']
    fileName = request.POST['filename']
    path = os.path.join('static', 'images', 'uploaded_ticket_files', fileName)

    # Ensure the directory exists
    os.makedirs(os.path.dirname(path), exist_ok=True)

    # If the file already exists, generate a new filename
    index = 1
    base_filename, extension = os.path.splitext(fileName)
    while os.path.exists(path):
        new_filename = f"{base_filename}_{index}{extension}"
        path = os.path.join('static', 'images', 'uploaded_ticket_files', new_filename)
        index += 1

    # Write the entire file
    with open(path, 'wb+') as destination:
        destination.write(file.read())

    return JsonResponse({'data': 'Uploaded Successfully', 'existingPath': path})


@staff_login_required
def add_ticket_update(request, ticket_id):
    ticket = get_object_or_404(Ticket, id=ticket_id)

    if request.method == 'POST':
        ticket_update = TicketUpdate(
            ticket=ticket,
            description=request.POST.get('description'),
            added_by=request.user,
            date_added=datetime.now(),
        )
        ticket_update.save()

        file_paths = request.POST.getlist('filePath') 

        for file_path in file_paths:
            ticket_attachment = TicketAttachment(
                ticket_update=ticket_update,
                file_path=file_path  
            )
            ticket_attachment.save()

        return redirect('ticketdetails', ticket_number=ticket.ticket_number)

    context = {
        'ticket': ticket,


    }

    return render(request, 'add_templates/customer-add-ticket.html', context)
