from waapi.utils import send_wallet_notification, send_wallet_cost_notification, send_create_user_notification
import time
from django.conf import settings
from userauth.models import MessageWhatsappTemplate
from django.template import Template, Context
import json
from django.shortcuts import get_object_or_404, render, redirect
from django.views import View
from django.urls import reverse
from django.core.paginator import Paginator
from django.db.models import Q
from django.contrib import messages
from django.db import transaction
from .models import Doctor, Technician
from core.models import Service
from patient.models import Patient
from reservation.models import Reservation
from .forms import DoctorCreateForm, TechnicianCreateForm
from django.views.decorators.http import require_http_methods
from django.http import HttpRequest, JsonResponse
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.core.validators import RegexValidator
import re
from datetime import datetime
from django.core.exceptions import ValidationError
import time


#  confirmed Exam(Send to Dr)
#  Patient Payment
#
#
# فرض: شماره موبایل باید با 79 شروع بشه و 11 رقم باشه
phone_regex = RegexValidator(
    regex=r'^\d{1,15}$',
    message=""
)

@login_required
def get_technicians_list(request):
    """دریافت لیست دسته‌بندی داروها"""
    try:
        technicians = Technician.objects.all()
        technicians_data = []
        for technician in technicians:
            technicians_data.append({
                'id': technician.id,
                'wallet': technician.wallet if technician.wallet else 0,
                'name': technician.get_full_name()
            })

        return JsonResponse({'success': True, 'technicians': technicians_data})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})
@login_required
def get_doctors_list(request):
    """دریافت لیست دسته‌بندی داروها"""
    try:
        doctors = Doctor.objects.all()
        print("doctors=",doctors)
        doctors_data = []
        for doctor in doctors:
            doctors_data.append({
                'id': doctor.id,
                'wallet': doctor.wallet if doctor.wallet else 0,
                'name': doctor.get_full_name()
            })
        print("doctors_data=",doctors_data)

        return JsonResponse({'success': True, 'doctors': doctors_data})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})
@method_decorator(login_required, name='dispatch')
class DoctorGetView(View):
    def get(self, request, pk):
        # آیا این درخواست برای API (json) است؟
        is_json = request.headers.get('Accept') == 'application/json' or request.GET.get('format') == 'json'

        doctor = Doctor.objects.get(id=pk)
        if is_json:
            results = []
            results.append({
                'id': doctor.id,
                'name': doctor.get_full_name(),
                'first_name': doctor.first_name,
                'last_name': doctor.last_name,
                'phone_number': doctor.phone_number,
                'country_code': doctor.country_code,
                'date_of_birth': doctor.date_of_birth,
                'specialty': doctor.specialty,
                'gender': doctor.gender,
                'address': doctor.address,
                'profile_picture': doctor.profile_picture.url if doctor.profile_picture else None,
                'identifier': doctor.identifier,
                'biography': doctor.biography,
                'status': doctor.status,
            })
            return JsonResponse({'success': True, 'results': results})


@method_decorator(login_required, name='dispatch')
class DoctorsView(View):
    def get(self, request):
        # آیا این درخواست برای API (json) است؟
        is_json = request.headers.get('Accept') == 'application/json' or request.GET.get('format') == 'json'


        doctor_list = Doctor.objects.all().order_by('id')
        search_query = request.GET.get('searchQuery', '').strip()
        filter_type = request.GET.get('filterType', 'name')

        if search_query:
            if filter_type == 'name':
                doctor_list = Doctor.objects.filter(
                    Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query)).order_by('first_name')
            if filter_type == 'phone_number':
                doctor_list = Doctor.objects.filter(
                    Q(phone_number__icontains=search_query)).order_by('id')
            if filter_type == 'specialty':
                doctor_list = Doctor.objects.filter(
                    Q(specialty__icontains=search_query)).order_by('id')
            if filter_type == 'id':
                doctor_list = Doctor.objects.filter(
                    Q(id=int(search_query))).order_by('id')

        if is_json:
            results = []
            for doctor in doctor_list:
                results.append({
                    'id': doctor.id,
                    'name': doctor.get_full_name(),
                    'first_name': doctor.first_name,
                    'last_name': doctor.last_name,
                    'phone_number': doctor.phone_number,
                    'country_code': doctor.country_code,
                    'date_of_birth': doctor.date_of_birth,
                    'specialty': doctor.specialty,
                    'gender': doctor.gender,
                    'address': doctor.address,
                    'profile_picture': doctor.profile_picture.url if doctor.profile_picture else None,
                    'identifier': doctor.identifier,
                    'biography': doctor.biography,
                    'status': doctor.status,
                })
            return JsonResponse({'success': True, 'results': results})

        # ============================
        # حالت رندر قالب HTML
        # ============================

        doctor_paginator = Paginator(doctor_list, 10)
        doctor_page_number = request.GET.get('service_page')
        page_obj = doctor_paginator.get_page(doctor_page_number)

        context = {
            'page_obj': page_obj,
            'search_query': search_query,
            'filter_type': filter_type,
        }

        return render(request, 'doctor/setting-doctor.html', context)


@login_required
def all_services(request):
    service_list = Service.objects.filter(status='active').order_by('id')
    services = []
    for service in service_list:
        services.append({
            'id': service.id,
            'name': service.name,
            'unit_price': service.unit_price,
            'status': service.status,
        })
    results = {"services": services}
    return JsonResponse({'success': True, 'results': results})


@login_required
def doctors_technician_services(request, service_id):
    doctor_list = Doctor.objects.filter(status='active').order_by('id')
    technician_list = Technician.objects.filter(status='active').order_by('id')
    service_list = Service.objects.filter(status='active').order_by('id')

    doctors = []
    for doctor in doctor_list:
        doctors.append({
            'id': doctor.id,
            'name': doctor.get_full_name(),
            'status': doctor.status,
        })
    technician_list = Technician.objects.filter(status='active').order_by('id')
    technicians = []
    for technician in technician_list:
        technician_services = technician.services.all()
        for tec_service in technician_services:
            if tec_service.id == int(service_id):
                technicians.append({
                    'id': technician.id,
                    'name': technician.get_full_name(),
                    'status': technician.status,
                })
    services = []
    for service in service_list:
        services.append({
            'id': service.id,
            'name': service.name,
            'unit_price': service.unit_price,
            'status': service.status,
        })
    results = {"doctors": doctors, "technicians": technicians, "services": services}
    return JsonResponse({'success': True, 'results': results})

@login_required
def patients_services(request, service_id,messageType):
    reservations = Reservation.objects.exclude(status='canceled')
    try:
        messageType=str(messageType)
        service_id = int(service_id)
        if service_id != 999:
            service_obj = Service.objects.get(id=service_id)
            service_name = service_obj.name
            reservations = reservations.filter(service=service_obj)
        else:
            service_name = 'all'
        active_reservation_patient_ids = reservations.values_list(
            'patient_id', flat=True
        ).distinct()
        if messageType == 'patient_without_service':
        # بیمارانی که رزرویشن فعال ندارند برای این سرویس خاص
            patient_list = Patient.objects.exclude(
                id__in=active_reservation_patient_ids
            )
        else:
            patient_list = Patient.objects.filter(
                id__in=active_reservation_patient_ids
            )
        patients = []
        for patient in patient_list:
            patients.append({
                'id': patient.id,
                'name': patient.get_full_name()
            })
        results = {"patients": patients}
        return JsonResponse({'success': True, 'results': results})
    except Exception as e:
        print(e)
        return JsonResponse({'success': False, 'error': 'error'})




@login_required
def techniciants_service(request, service_id):
    technician_list = Technician.objects.filter(status='active').order_by('id')

    technicians = []
    for technician in technician_list:
        services = technician.services.all()
        for service in services:
            if service.id == int(service_id):
                technicians.append({
                    'id': technician.id,
                    'name': technician.get_full_name(),
                    'status': technician.status,
                })
    results = {"technicians": technicians}
    return JsonResponse({'success': True, 'results': results})


@login_required
@require_http_methods(["GET"])
def search_doctors(request):
    search_query = request.GET.get('q', '')
    filter_type = request.GET.get('filterType', 'name')

    if not search_query:
        return JsonResponse({'success': False, 'error': 'Search term cannot be empty.'})

    try:
        doctor_list = Doctor.objects.all().order_by('id')

        # اعمال فیلتر جستجو
        if filter_type == 'name':
            doctor_list = Doctor.objects.filter(
                Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query)).order_by('first_name')
        if filter_type == 'phone_number':
            doctor_list = Doctor.objects.filter(
                Q(phone_number__icontains=search_query)).order_by('phone_number')
        if filter_type == 'specialty':
            doctor_list = Doctor.objects.filter(
                Q(specialty__icontains=search_query)).order_by('specialty')
        if filter_type == 'id':
            doctor_list = Doctor.objects.filter(
                Q(id=int(search_query))).order_by('id')
        # محدود کردن تعداد نتایج برای عملکرد بهتر
        # services = services[:50]

        # تبدیل نتایج به دیکشنری
        results = []
        for doctor in doctor_list:
            results.append({
                'id': doctor.id,
                'name': doctor.get_full_name(),
                'first_name': doctor.first_name,
                'last_name': doctor.last_name,
                'phone_number': doctor.phone_number,
                'country_code': doctor.country_code,
                'date_of_birth': doctor.date_of_birth,
                'specialty': doctor.specialty,
                'gender': doctor.gender,
                'address': doctor.address,
                'profile_picture': doctor.profile_picture.url if doctor.profile_picture else None,
                'identifier': doctor.identifier,
                'biography': doctor.biography,
                'status': doctor.status,
            })

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

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


class DoctorNewCreateView(View):
    def post(self, request):
        try:
            if request.content_type == 'application/json':
                data = json.loads(request.body)
                profile_picture = None  # فایل وجود ندارد در این حالت
            else:
                data = request.POST
                profile_picture = request.FILES.get('profile_picture')

            # داده‌های ورودی
            first_name = data.get('first_name', '').strip()
            last_name = data.get('last_name', '').strip()
            phone_number = data.get('phone_number', '').strip()
            country_code = data.get('country_code', '').strip()
            print("country_code=", country_code)
            print("phone_number=", phone_number)

            date_of_birth = data.get('date_of_birth', '').strip()
            specialty = data.get('specialty', '').strip()
            gender = data.get('gender', 'None').strip()
            address = data.get('address', '').strip()
            status = data.get('status', 'active').strip()
            identifier = data.get('identifier', None)
            biography = data.get('biography', '').strip()

            # اعتبارسنجی الزامی‌ها
            if not first_name or not last_name:
                return JsonResponse({'success': False, 'error': 'The first name and last name are required.'})

            if not date_of_birth:
                return JsonResponse({'success': False, 'error': 'The Birth date is required.'})

            try:
                dob = datetime.strptime(date_of_birth, '%Y-%m-%d').date()
                if dob > datetime.now().date():
                    return JsonResponse({'success': False, 'error': 'The birth date cant be in future.'})
            except ValueError:
                return JsonResponse({'success': False, 'error': 'The birth date format is incorrect(YYYY-MM-DD).'})

            if not re.match(r'^\d{1,15}$', phone_number):
                return JsonResponse(
                    {'success': False, 'error': 'The phone number must be between 1 and 15 like 9121234455.'})
            phone_number = phone_number
            if gender not in dict(Doctor.GENDER):
                gender = 'None'

            if status not in dict(Doctor.STATUS_CHOICES):
                status = 'active'

            # ساخت شی پزشک
            doctor = Doctor.objects.create(
                first_name=first_name,
                last_name=last_name,
                phone_number=phone_number,
                country_code=country_code,
                date_of_birth=dob,
                specialty=specialty,
                gender=gender,
                address=address,
                status=status,
                identifier=identifier,
                biography=biography,
                profile_picture=profile_picture  # افزودن فایل
            )
            send_create_user_notification("doctor", doctor)

            return JsonResponse({
                'success': True,
                'id': doctor.id,
                'first_name': doctor.first_name,
                'last_name': doctor.last_name,
                'full_name': doctor.get_full_name(),
                'phone_number': doctor.phone_number,
                'country_code': doctor.country_code,
                'date_of_birth': doctor.date_of_birth.isoformat(),
                'specialty': doctor.specialty,
                'gender': doctor.gender,
                'address': doctor.address,
                'identifier': doctor.identifier,
                'biography': doctor.biography,
                'status': doctor.status,
                'created_at': doctor.created_at.isoformat() if doctor.created_at else None,
                'user_id': doctor.user.id if doctor.user else None,
                'profile_picture': doctor.profile_picture.url if doctor.profile_picture else None,
            })

        except json.JSONDecodeError:
            return JsonResponse({'success': False, 'error': 'Error.'})
        except ValidationError as ve:
            return JsonResponse({'success': False, 'error': ve.message})
        except Exception as e:
            return JsonResponse({'success': False, 'error': f'Error: {str(e)}'})


class DoctorUpdateView(View):
    def post(self, request, pk):
        print("in DoctorUpdateView")

        try:
            doctor = get_object_or_404(Doctor, id=pk)
            if request.user.access_level != "Administrator":
                if request.user != doctor.user:
                    return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)


            # گرفتن داده‌ها از request.POST
            doctor.first_name = request.POST.get('first_name', '').strip()
            doctor.last_name = request.POST.get('last_name', '').strip()
            doctor.phone_number = request.POST.get('phone_number', '').strip()
            doctor.country_code = request.POST.get('country_code', '').strip()
            # doctor.phone_number = country_code+phone_number
            print("country_code=", doctor.country_code)
            print("phone_number=", doctor.phone_number)
            doctor.date_of_birth = request.POST.get('date_of_birth', '').strip()
            doctor.specialty = request.POST.get('specialty', '').strip()
            doctor.gender = request.POST.get('gender', '').strip()
            doctor.address = request.POST.get('address', '').strip()
            doctor.status = request.POST.get('status', '').strip()
            doctor.identifier = request.POST.get('identifier') or None
            doctor.biography = request.POST.get('biography', '').strip()

            # اگر فایل فرستاده شده باشه
            if request.FILES.get('profile_picture'):
                doctor.profile_picture = request.FILES['profile_picture']

            # اعتبارسنجی ساده
            if not doctor.first_name or not doctor.last_name:
                return JsonResponse({'success': False, 'error': 'The first name & last name are required.'})

            if not doctor.phone_number.isdigit() or not (1 <= len(doctor.phone_number) <= 15):
                return JsonResponse({'success': False, 'error': 'The phone number must be between 1 and 15.'})

            try:
                doctor.full_clean()  # اجرای ولیدیتورها
            except ValidationError as ve:
                return JsonResponse({'success': False, 'error': ve.message_dict})

            doctor.save()

            return JsonResponse({
                'success': True,
                "id": doctor.id,
                "first_name": doctor.first_name,
                "last_name": doctor.last_name,
                "phone_number": doctor.phone_number,
                "country_code": doctor.country_code,
                "date_of_birth": str(doctor.date_of_birth),
                "specialty": doctor.specialty,
                "gender": doctor.gender,
                "address": doctor.address,
                "status": doctor.status,
                "identifier": doctor.identifier,
                "biography": doctor.biography,
                "profile_picture": doctor.profile_picture.url if doctor.profile_picture else None,
            })

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


class ChangeDoctorStatusView(View):
    def post(self, request, *args, **kwargs):
        data = json.loads(request.body)
        doctor_id = data.get('id')
        new_status = data.get('status')

        try:
            doctor = Doctor.objects.get(id=doctor_id)
            doctor.status = new_status
            doctor.save()
            return JsonResponse({'success': True})
        except Doctor.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Doctor not found'}, status=404)
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=500)


class DoctorDeleteView(View):
    def post(self, request, id):
        try:
            doctor = get_object_or_404(Doctor, id=id)
            doctor.delete()
            return JsonResponse({'success': True})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)})


# #########################################################
@method_decorator(login_required, name='dispatch')
class TechnicianGetView(View):
    def get(self, request, pk):
        # آیا این درخواست برای API (json) است؟
        is_json = request.headers.get('Accept') == 'application/json' or request.GET.get('format') == 'json'

        technician = Technician.objects.get(id=pk)
        if is_json:
            results = []
            results.append({
                'id': technician.id,
                'name': technician.get_full_name(),
                'first_name': technician.first_name,
                'last_name': technician.last_name,
                'phone_number': technician.phone_number,
                'country_code': technician.country_code,
                'date_of_birth': technician.date_of_birth,
                'specialty': technician.specialty,
                'gender': technician.gender,
                'address': technician.address,
                'profile_picture': technician.profile_picture.url if technician.profile_picture else None,
                'identifier': technician.identifier,
                'biography': technician.biography,
                'status': technician.status,
            })
            return JsonResponse({'success': True, 'results': results})


@method_decorator(login_required, name='dispatch')
class TechniciansView(View):
    def get(self, request):
        # آیا این درخواست برای API (json) است؟
        is_json = request.headers.get('Accept') == 'application/json' or request.GET.get('format') == 'json'


        technician_list = Technician.objects.all().order_by('id')
        search_query = request.GET.get('searchQuery', '').strip()
        filter_type = request.GET.get('filterType', 'name')

        if search_query:
            if filter_type == 'name':
                technician_list = Technician.objects.filter(
                    Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query)).order_by('first_name')
            if filter_type == 'phone_number':
                technician_list = Technician.objects.filter(
                    Q(phone_number__icontains=search_query)).order_by('id')
            if filter_type == 'specialty':
                technician_list = Technician.objects.filter(
                    Q(specialty__icontains=search_query)).order_by('id')
            if filter_type == 'id':
                technician_list = Technician.objects.filter(
                    Q(id=int(search_query))).order_by('id')

        services = Service.objects.all()
        services_list = []
        for service in services:
            services_list.append({'id': service.id, 'name': service.name})
        if is_json:
            results = []
            for technician in technician_list:
                servises_tec = []
                for service in technician.services.all():
                    servises_tec.append({'id': service.id, 'name': service.name})
                results.append({
                    'id': technician.id,
                    'name': technician.get_full_name(),
                    'first_name': technician.first_name,
                    'last_name': technician.last_name,
                    'phone_number': technician.phone_number,
                    'country_code': technician.country_code,
                    'date_of_birth': technician.date_of_birth,
                    'specialty': technician.specialty,
                    'gender': technician.gender,
                    'address': technician.address,
                    'profile_picture': technician.profile_picture.url if technician.profile_picture else None,
                    'identifier': technician.identifier,
                    'biography': technician.biography,
                    'status': technician.status,
                    'services': services_list,
                    'service_objs': servises_tec,
                })
            return JsonResponse({'success': True, 'results': results})

        # ============================
        # حالت رندر قالب HTML
        # ============================

        technician_paginator = Paginator(technician_list, 10)
        technician_page_number = request.GET.get('service_page')
        page_obj = technician_paginator.get_page(technician_page_number)

        service_paginator = Paginator(services, 10)
        service_page_number = request.GET.get('service_page')
        services = service_paginator.get_page(service_page_number)

        context = {
            'page_obj': page_obj,
            'search_query': search_query,
            'filter_type': filter_type,
            'services': services
        }

        return render(request, 'technician/setting-technician.html', context)


@login_required
@require_http_methods(["GET"])
def search_technicians(request):

    search_query = request.GET.get('q', '')
    filter_type = request.GET.get('filterType', 'name')

    if not search_query:
        return JsonResponse({'success': False, 'error': 'Search term cannot be empty.'})

    try:
        technician_list = Technician.objects.all().order_by('id')

        # اعمال فیلتر جستجو
        if filter_type == 'name':
            technician_list = Technician.objects.filter(
                Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query)).order_by('first_name')
        if filter_type == 'phone_number':
            technician_list = Technician.objects.filter(
                Q(phone_number__icontains=search_query)).order_by('phone_number')
        if filter_type == 'specialty':
            technician_list = Technician.objects.filter(
                Q(specialty__icontains=search_query)).order_by('specialty')
        if filter_type == 'id':
            technician_list = Technician.objects.filter(
                Q(id=int(search_query))).order_by('id')
        # محدود کردن تعداد نتایج برای عملکرد بهتر
        # services = services[:50]

        # تبدیل نتایج به دیکشنری
        results = []
        for technician in technician_list:
            results.append({
                'id': technician.id,
                'name': technician.get_full_name(),
                'first_name': technician.first_name,
                'last_name': technician.last_name,
                'phone_number': technician.phone_number,
                'country_code': technician.country_code,
                'date_of_birth': technician.date_of_birth,
                'specialty': technician.specialty,
                'gender': technician.gender,
                'address': technician.address,
                'profile_picture': technician.profile_picture.url if technician.profile_picture else None,
                'identifier': technician.identifier,
                'biography': technician.biography,
                'status': technician.status,
            })

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

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


class TechnicianNewCreateView(View):
    def post(self, request):
        try:
            if request.content_type == 'application/json':
                data = json.loads(request.body)
                profile_picture = None  # فایل وجود ندارد در این حالت
            else:
                data = request.POST
                profile_picture = request.FILES.get('profile_picture')
            print("data=",data)
            # داده‌های ورودی
            first_name = data.get('first_name', '').strip()
            last_name = data.get('last_name', '').strip()
            phone_number = data.get('phone_number', '').strip()
            country_code = data.get('country_code', '').strip()
            date_of_birth = data.get('date_of_birth', '').strip()
            specialty = data.get('specialty', '').strip()
            gender = data.get('gender', 'None').strip()
            address = data.get('address', '').strip()
            status = data.get('status', 'active').strip()
            identifier = data.get('identifier', None)
            biography = data.get('biography', '').strip()

            # اعتبارسنجی الزامی‌ها
            if not first_name or not last_name:
                return JsonResponse({'success': False, 'error': 'first name & last name are required'})

            if not date_of_birth:
                return JsonResponse({'success': False, 'error': 'the birth date is required.'})

            try:
                dob = datetime.strptime(date_of_birth, '%Y-%m-%d').date()
                if dob > datetime.now().date():
                    return JsonResponse({'success': False, 'error': 'The birth date cant be in future.'})
            except ValueError:
                return JsonResponse({'success': False, 'error': 'The format of birth date must be like (YYYY-MM-DD).'})

            if not re.match(r'^\d{1,15}$', phone_number):
                return JsonResponse(
                    {'success': False, 'error': 'The phone number must be between 1 and 15 digits.'})
            if gender not in dict(Technician.GENDER):
                gender = 'None'

            if status not in dict(Technician.STATUS_CHOICES):
                status = 'active'

            # ساخت شی پزشک
            technician = Technician.objects.create(
                first_name=first_name,
                last_name=last_name,
                phone_number=phone_number,
                country_code=country_code,
                date_of_birth=dob,
                specialty=specialty,
                gender=gender,
                address=address,
                status=status,
                identifier=identifier,
                biography=biography,
                profile_picture=profile_picture  # افزودن فایل
            )
            send_create_user_notification("technician", technician)
            service_ids = data.getlist(
                'services') if request.content_type != 'application/json' else data.get('services', [])
            service_obj = []
            if service_ids:
                technician.services.set(service_ids)
                for id_service in service_ids:
                    service = Service.objects.get(id=int(id_service))
                    service_obj.append({'id': service.id, 'name': service.name})
            print("service_obj = ",service_obj)
            return JsonResponse({
                'success': True,
                'id': technician.id,
                'service_objs': service_obj,
                'first_name': technician.first_name,
                'last_name': technician.last_name,
                'full_name': technician.get_full_name(),
                'phone_number': technician.phone_number,
                'country_code': technician.country_code,
                'date_of_birth': technician.date_of_birth.isoformat(),
                'specialty': technician.specialty,
                'gender': technician.gender,
                'address': technician.address,
                'identifier': technician.identifier,
                'biography': technician.biography,
                'status': technician.status,
                'created_at': technician.created_at.isoformat() if technician.created_at else None,
                'user_id': technician.user.id if technician.user else None,
                'profile_picture': technician.profile_picture.url if technician.profile_picture else None,
            })

        except json.JSONDecodeError:
            return JsonResponse({'success': False, 'error': 'The json format is incorrect.'})
        except ValidationError as ve:
            return JsonResponse({'success': False, 'error': ve.message})
        except Exception as e:
            return JsonResponse({'success': False, 'error': f'Error: {str(e)}'})


class TechnicianUpdateView(View):
    def post(self, request, pk):
        try:
            technician = get_object_or_404(Technician, id=pk)

            # گرفتن داده‌ها از request.POST
            technician.first_name = request.POST.get('first_name', '').strip()
            technician.last_name = request.POST.get('last_name', '').strip()
            technician.phone_number = request.POST.get('phone_number', '').strip()
            technician.country_code = request.POST.get('country_code', '').strip()
            technician.date_of_birth = request.POST.get('date_of_birth', '').strip()
            technician.specialty = request.POST.get('specialty', '').strip()
            technician.gender = request.POST.get('gender', '').strip()
            technician.address = request.POST.get('address', '').strip()
            technician.status = request.POST.get('status', '').strip()
            technician.identifier = request.POST.get('identifier') or None
            technician.biography = request.POST.get('biography', '').strip()

            # اگر فایل فرستاده شده باشه
            if request.FILES.get('profile_picture'):
                technician.profile_picture = request.FILES['profile_picture']

            if not technician.first_name or not technician.last_name:
                return JsonResponse({'success': False, 'error': 'first name & last name are required'})

            if not technician.date_of_birth:
                return JsonResponse({'success': False, 'error': 'the birth date is required.'})

            try:
                dob = datetime.strptime(technician.date_of_birth, '%Y-%m-%d').date()
                if dob > datetime.now().date():
                    return JsonResponse({'success': False, 'error': 'The birth date cant be in future.'})
            except ValueError:
                return JsonResponse({'success': False, 'error': 'The format of birth date must be like (YYYY-MM-DD).'})

            if not re.match(r'^\d{1,15}$', technician.phone_number):
                return JsonResponse(
                    {'success': False, 'error': 'The phone number must be between 1 and 15 digits.'})

            try:
                technician.full_clean()  # اجرای ولیدیتورها
            except ValidationError as ve:
                return JsonResponse({'success': False, 'error': ve.message_dict})

            technician.save()

            service_ids = request.POST.getlist('services')

            service_obj = []
            if service_ids:
                technician.services.set(service_ids)
                for id_service in service_ids:
                    service = Service.objects.get(id=int(id_service))
                    service_obj.append({'id': service.id, 'name': service.name})

            return JsonResponse({
                'success': True,
                "id": technician.id,
                "first_name": technician.first_name,
                "last_name": technician.last_name,
                "phone_number": technician.phone_number,
                "country_code": technician.country_code,
                "date_of_birth": str(technician.date_of_birth),
                "specialty": technician.specialty,
                "gender": technician.gender,
                "address": technician.address,
                "status": technician.status,
                "identifier": technician.identifier,
                "biography": technician.biography,
                "profile_picture": technician.profile_picture.url if technician.profile_picture else None,
                "services": service_obj,
            })

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


class ChangeTechnicianStatusView(View):
    def post(self, request, *args, **kwargs):
        data = json.loads(request.body)
        technician_id = data.get('id')
        new_status = data.get('status')

        try:
            technician = Technician.objects.get(id=technician_id)
            technician.status = new_status
            technician.save()
            return JsonResponse({'success': True})
        except Technician.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Technician not found'}, status=404)
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)}, status=500)


class TechnicianDeleteView(View):
    def post(self, request, id):
        try:
            technician = get_object_or_404(Technician, id=id)
            technician.delete()
            return JsonResponse({'success': True})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)})


# #########################################################


# #######################################################
# #######################################################
# #######################################################
# #######################################################
# #######################################################


class DoctorView(View):
    """Handles viewing doctor settings."""

    def get(self, request, *args, **kwargs):
        # Get search parameters from GET request
        search_query = request.GET.get('searchQuery', '')
        filter_type = request.GET.get('filterType', 'name')

        # Check if there's a search query
        if search_query:
            if filter_type == 'name':
                doctor_list = Doctor.objects.filter(
                    Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query)).order_by('first_name')
            elif filter_type == 'phone_number':
                doctor_list = Doctor.objects.filter(
                    phone_number__icontains=search_query).order_by('id')
            elif filter_type == 'id':
                doctor_list = Doctor.objects.filter(id__icontains=search_query).order_by('id')
            elif filter_type == 'speciality':
                doctor_list = Doctor.objects.filter(
                    specialty__icontains=search_query).order_by('speciality')
        else:
            doctor_list = Doctor.objects.all()  # No search, list all doctors

        doctor_list = doctor_list.order_by('first_name')

        # Paginate the results (either all doctors or search results)
        paginator = Paginator(doctor_list, 10)  # Show 10 doctors per page
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)

        # Passing the search and paginated data to the template
        context = {
            'page_obj': page_obj,  # Pagination object for the current page
            'search_query': search_query,  # Keep the search query
            'filter_type': filter_type,  # Keep the filter type
        }
        return render(request, 'doctor/setting-doctor.html', context)

#  #########################################################
class DoctorCreateView(View):
    def get(self, request):
        form = DoctorCreateForm()
        return render(request, 'doctor/setting-doctor-create.html', {'form': form})

    def post(self, request):
        form = DoctorCreateForm(request.POST, request.FILES)
        if form.is_valid():
            clean_data = form.cleaned_data
            Doctor.objects.create(
                first_name=clean_data['first_name'],
                last_name=clean_data['last_name'],
                phone_number=clean_data['phone_number'],
                date_of_birth=clean_data['date_of_birth'],
                specialty=clean_data['specialty'],
                gender=clean_data['gender'],
                address=clean_data['address'],
                profile_picture=clean_data['profile_picture']
            )
            send_create_user_notification("doctor", doctor)
            messages.success(request, f"Doctor {clean_data['last_name']} created successfully.")
            return redirect('doctor:doctors')

        else:
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f"{field.capitalize()}: {error}")

        return render(request, 'doctor/setting-doctor-create.html', {'form': form})


class DoctorEditView(View):
    def get(self, request: HttpRequest, id):
        doctor = get_object_or_404(Doctor, id=id)
        form = DoctorCreateForm(initial={
            'first_name': doctor.first_name,
            'last_name': doctor.last_name,
            'phone_number': doctor.phone_number,
            'date_of_birth': doctor.date_of_birth,
            'specialty': doctor.specialty,
            'gender': doctor.gender,
            'address': doctor.address,
            'profile_picture': doctor.profile_picture.url if doctor.profile_picture else None,
        })
        return render(request, 'doctor/setting-doctor-edit.html', {'form': form, 'doctor': doctor})

    def post(self, request: HttpRequest, id):
        doctor = get_object_or_404(Doctor, id=id)
        form = DoctorCreateForm(request.POST, request.FILES)

        if form.is_valid():
            clean_data = form.cleaned_data

            doctor.first_name = clean_data['first_name']
            doctor.last_name = clean_data['last_name']
            doctor.phone_number = clean_data['phone_number']
            doctor.date_of_birth = clean_data['date_of_birth']
            doctor.specialty = clean_data['specialty']
            doctor.gender = clean_data['gender']
            doctor.address = clean_data['address']
            if 'profile_picture' in request.FILES:
                doctor.profile_picture = request.FILES['profile_picture']

            doctor.save()
            messages.success(
                request, "Doctor information updated successfully.")
            return redirect('doctor:doctors')
        else:
            # If the form is not valid, add error messages
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f"{field.capitalize()}: {error}")

        return render(request, 'doctor/setting-doctor-edit.html', {'form': form, 'doctor': doctor})


###########################################################################


class TechnicianView(View):
    """Handles viewing technician settings."""

    def get(self, request, *args, **kwargs):
        # Get search parameters from GET request
        search_query = request.GET.get('searchQuery', '')
        filter_type = request.GET.get('filterType', 'name')

        # Check if there's a search query
        if search_query:
            if filter_type == 'name':
                technician_list = Technician.objects.filter(
                    Q(first_name__icontains=search_query) | Q(
                        last_name__icontains=search_query)
                )
            elif filter_type == 'phone':
                technician_list = Technician.objects.filter(
                    phone_number__icontains=search_query)
            elif filter_type == 'id':
                technician_list = Technician.objects.filter(
                    id__icontains=search_query)
            elif filter_type == 'speciality':
                technician_list = Technician.objects.filter(
                    specialty__icontains=search_query)
        else:
            technician_list = Technician.objects.all()  # No search, list all technicians

        # Order the technician list before paginating
        # You can change the field to order by as needed
        technician_list = technician_list.order_by('first_name')

        # Paginate the results (either all technicians or search results)
        # Show 10 technicians per page
        paginator = Paginator(technician_list, 10)
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)

        # Passing the search and paginated data to the template
        context = {
            'page_obj': page_obj,  # Pagination object for the current page
            'search_query': search_query,  # Keep the search query
            'filter_type': filter_type,  # Keep the filter type
        }
        return render(request, 'technician/setting-technician.html', context)


class TechnicianCreateView(View):
    """Handles technician creation (GET for form display, POST for form submission)."""

    def get(self, request: HttpRequest):
        form = TechnicianCreateForm()
        return render(
            request, 'technician/setting-technician-create.html', {
                'form': form}
        )

    def post(self, request: HttpRequest):
        form = TechnicianCreateForm(request.POST, request.FILES)
        if form.is_valid():
            clean_data = form.cleaned_data

            Technician.objects.create(
                # user=?,  # todo: add it in the future
                first_name=clean_data['first_name'],
                last_name=clean_data['last_name'],
                phone_number=clean_data['phone_number'],
                date_of_birth=clean_data['date_of_birth'],
                specialty=clean_data['specialty'],
                gender=clean_data['gender'],
                address=clean_data['address'],
                profile_picture=clean_data['profile_picture']
            )
            send_create_user_notification("technician", technician)

            messages.success(request, f"Technician {clean_data['last_name']} created successfully.")

            return redirect('doctor:technicians')

        else:
            # If the form is not valid, add error messages
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f"{field.capitalize()}: {error}")

        # If form is invalid, re-render the form with validation errors
        return render(
            request, 'technician/setting-technician-create.html', {
                'form': form}
        )


class TechnicianEditView(View):

    def get(self, request: HttpRequest, id):
        technician = Technician.objects.get(id=id)
        form = TechnicianCreateForm(initial={
            'first_name': technician.first_name,
            'last_name': technician.last_name,
            'phone_number': technician.phone_number,
            'date_of_birth': technician.date_of_birth,
            'specialty': technician.specialty,
            'gender': technician.gender,
            'address': technician.address,
            'profile_picture': technician.profile_picture
        })
        return render(request, 'technician/setting-technician-edit.html', {'form': form, 'technician': technician})

    def post(self, request: HttpRequest, id):
        technician = Technician.objects.get(id=id)
        form = TechnicianCreateForm(request.POST, request.FILES)

        if form.is_valid():
            clean_data = form.cleaned_data

            technician.first_name = clean_data['first_name']
            technician.last_name = clean_data['last_name']
            technician.phone_number = clean_data['phone_number']
            technician.date_of_birth = clean_data['date_of_birth']
            technician.specialty = clean_data['specialty']
            technician.gender = clean_data['gender']
            technician.address = clean_data['address']
            if 'profile_picture' in request.FILES:
                technician.profile_picture = request.FILES['profile_picture']

            technician.save()
            messages.success(
                request, "Technician information updated successfully.")
            return redirect('doctor:technicians')  # Update to correct URL
        else:
            # If the form is not valid, add error messages
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f"{field.capitalize()}: {error}")

        return render(request, 'technician/setting-technician-edit.html', {'form': form, 'technician': technician})


class TechnicianDeleteView(View):
    def post(self, request: HttpRequest, id: int):
        technician = get_object_or_404(Technician, id=id)

        try:
            with transaction.atomic():
                technician_name = technician.get_full_name()
                technician.delete()
                messages.success(request, f"Technician '{technician_name}' has been successfully deleted.")
        except Exception as e:
            messages.error(
                request, f"An error occurred while deleting the technician: {str(e)}")

        return redirect(reverse("doctor:technicians"))
