# from core.management.utils import send_whatsapp_message
# from core.management.utils import send_wallet_notification, send_wallet_cost_notification, send_create_user_notification
from waapi.utils import send_whatsapp, 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
# views.py - فایل ویو‌های پروژه
from django.views.decorators.http import require_http_methods

from django.views.decorators.http import require_POST

from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.contrib import messages
from django.utils.decorators import method_decorator
from django.db.models import Q
from django.http import JsonResponse

from .models import Patient, PatientImage, MedicalRecord
from core.models import ExchangeRate
from userauth.models import MessageWhatsappTemplate
from reservation.models import Reservation, ReservationChangeLog
from warehouse.models import Category,WarehouseItem
from .forms import PatientForm, PatientImageForm, MedicalRecordForm, ReservationForm
from django.contrib.auth.decorators import login_required
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.contrib import messages
from django.utils.decorators import method_decorator
from django.db.models import Q, Prefetch
from django.http import JsonResponse
from django.utils import timezone
from datetime import datetime, timedelta
from django.views import View
from django.http import HttpRequest
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.db import transaction
from django.template import Template, Context
import time
from decimal import Decimal
User = get_user_model()
@login_required
def patient_wallet_edit(request, patient_id):

    """Patient profile view"""
    patient = get_object_or_404(Patient, id=patient_id)
    print("patient=",patient.wallet)
    print("request=",request.POST)
    wallet_type = request.POST.get('wallet_type')
    amount = request.POST.get('amount')
    amount = Decimal(amount)
    print("amount=",amount)
    print("patient.wallet=",patient.wallet)
    patient_wallet = patient.wallet if patient.wallet else Decimal(0)
    print("patient_wallet=",patient_wallet)
    if wallet_type == 'add':
        patient_wallet += amount
        patient.wallet = patient_wallet
        patient.save()
        try:
            send_wallet_cost_notification(
                recipient_type='patient',
                person=patient,
                amount=amount,
                wallet_after=patient.wallet,
                phone=patient.country_code + patient.phone_number
            )
        except Exception as e:
            print(e)
        print("Add patient=",patient_wallet)

    if wallet_type == 'minus':
        patient_wallet -= amount
        patient.wallet = patient_wallet
        patient.save()
        try:
            send_wallet_notification(
                recipient_type='patient',
                person=patient,
                amount=amount,
                wallet_after=patient.wallet,
                phone=patient.country_code + patient.phone_number
            )
        except Exception as e:
            print(e)
        print("Minus patient=",patient_wallet)
    patient.wallet = patient_wallet
    patient.save()
    print("patient.wallet=",patient.wallet)
    try:
        return JsonResponse({'success': True,'wallet':patient.wallet})
    except Exception:
        return JsonResponse({"error": "Error"}, status=500)

class PatientNewCreateView(View):
    def post(self, request):
        try:
            if request.content_type == 'application/json':
                data = json.loads(request.body)
                profile_picture = None  # فایل وجود ندارد در این حالت
            else:
                data = request.POST
                print("data", data)
                profile_picture = request.FILES.get('profile_img')
                # patient_images0 = request.FILES.get('patient_images[0]')
                # patient_images1 = request.FILES.get('patient_images[1]')
            # داده‌های ورودی
            print("data== ", data)
            first_name = data.get('first_name', '').strip()
            last_name = data.get('last_name', '').strip()
            gender = data.get('gender', 'None').strip()
            date_of_birth = data.get('date_of_birth', '').strip()
            age = data.get('age', '')
            age = int(age)
            phone_number = data.get('phone_number', '').strip()
            country_code = data.get('country_code', '').strip()
            address = data.get('address', '')
            identifier = generate_random_id()
            biography = data.get('medical_records', '')
            reference_type = data.get('reference_type', '')
            leader_id = data.get('leaderSelectPatient', None)
            leader_id = int(leader_id) if leader_id else None

            print("leader_id== ", leader_id)

            # اعتبارسنجی الزامی‌ها
            try:
                if not first_name or not last_name:
                    return JsonResponse({'success': False, 'error': 'The first name and last name are required.'})

                if not age:
                    return JsonResponse({'success': False, 'error': 'The age is required.'})

                # dob = datetime.strptime(age, '%Y-%m-%d').date()
                # if dob > datetime.now().date():
                #     return JsonResponse({'success': False, 'error': 'The birth date cant be in future.'})
                if not re.match(r'^\d{1,15}$', phone_number):
                    return JsonResponse(
                        {'success': False, 'error': 'Phone number must be in international format without '+' (e.g. 9123456789).'})

                if gender not in dict(Patient.GENDER):
                    gender = 'None'
                # except Exception as e:
                #     return JsonResponse({'success': False, 'error': str(e)})



                # if status not in dict(Doctor.STATUS_CHOICES):
                #     status = 'active'
                # status = 'active'

                # ساخت شی پزشک
                patient = Patient.objects.create(
                    first_name=first_name,
                    last_name=last_name,
                    leader_id=leader_id,
                    phone_number=phone_number,
                    country_code=country_code,
                    age=age,
                    date_of_birth=date_of_birth,
                    gender=gender,
                    address=address,
                    identifier=identifier,
                    biography=biography,
                    profile_picture=profile_picture  # افزودن فایل
                )
                send_create_user_notification("patient", patient)
                if reference_type:
                    patient.reference_type = reference_type
                    if reference_type == 'Person':
                        identifier_name = data.get('identifier_name', '')
                        identifier_phone = data.get('identifier_phone', '')
                        patient.identifier_name = identifier_name
                        patient.identifier_phone = identifier_phone
                    if reference_type == 'SocialMedia':
                        social_media_type = data.get('social_media_type', '')
                        patient.social_media_type = social_media_type
                    patient.save()


                reservations = getattr(patient, 'ordered_reservations', [])

                if reservations:
                    has_reservations = True
                    latest_reservation_status = reservations[0].status
                    latest_reservation_date = reservations[0].reservation_date.isoformat()
                else:
                    has_reservations = False
                    latest_reservation_status = "-"
                    latest_reservation_date = "-"
                print("patient.wallet=",patient.wallet)
                patient_obj = {
                    'id': str(patient.id),
                    'wallet': patient.wallet,
                    'first_name': patient.first_name,
                    'last_name': patient.last_name,
                    'full_name': patient.get_full_name(),
                    'short_name': patient.get_short_name(),
                    'gender': patient.gender,
                    'age': patient.age if patient.age else None,
                    'date_of_birth': patient.date_of_birth if patient.date_of_birth else None,
                    'phone_number': patient.phone_number,
                    'country_code': patient.country_code,
                    'address': patient.address,
                    'identifier': str(patient.identifier),
                    'biography': patient.biography,
                    'created_at': patient.created_at.isoformat() if patient.created_at else None,
                    'user_id': str(patient.user.id) if patient.user else None,
                    'profile_picture': patient.profile_picture.url if patient.profile_picture else None,
                    'latest_reservation_date': str(latest_reservation_date),
                    'latest_reservation_status': str(latest_reservation_status),
                    'has_reservations': has_reservations,
                    'reference_type': patient.reference_type,
                    'social_media_type': patient.social_media_type,
                    'identifier_name': patient.identifier_name,
                    'identifier_phone': patient.identifier_phone,
                }
                medical_records = []
                for i in range(100):
                    record_type = data.get(f'medical_records[{str(i)}][record_type]', '')
                    if record_type:
                        record_type = data.get(f'medical_records[{str(i)}][record_type]', '').strip()
                        pregnancy_week = data.get(f'medical_records[{str(i)}][pregnancy_weeks]', 0)
                        if not pregnancy_week: pregnancy_week =0
                        else: pregnancy_week =int(pregnancy_week)
                        pregnancy_weeks = pregnancy_week
                        diabetes_type = data.get(f'medical_records[{str(i)}][diabetes_type]', '').strip()
                        hypertension_level = data.get(f'medical_records[{str(i)}][hypertension_level]', '').strip()
                        drugs = data.get(f'medical_records[{str(i)}][drugs]', '')
                        description = data.get(f'medical_records[{str(i)}][description]', '')
                        diagnosis_date = data.get(f'medical_records[{str(i)}][diagnosis_date]', '')
                        if diagnosis_date:
                            diagnosis_date = datetime.strptime(diagnosis_date, '%Y-%m-%d').date()
                        else:
                            diagnosis_date = None
                        status = data.get(f'medical_records[{str(i)}][status]', '').strip()
                        if record_type !="diabetes":
                            diabetes_type = ''
                        medical_record = MedicalRecord.objects.create(
                            patient_id=patient.id,
                            record_type=record_type,
                            diagnosis_date=diagnosis_date,
                            medications=drugs,
                            description=description,
                            status=status,
                            diabetes_type=diabetes_type,
                            blood_pressure=hypertension_level,
                            pregnancy_week=pregnancy_weeks  # افزودن فایل
                        )
                        medical_records.append(
                            {
                                "id": str(medical_record.id),
                                "patient_id": str(medical_record.patient_id),
                                "record_type": medical_record.record_type,
                                "diagnosis_date": medical_record.diagnosis_date.isoformat() if medical_record.diagnosis_date else None,
                                "medications": medical_record.medications,
                                "description": medical_record.description,
                                "status": medical_record.status,
                                "diabetes_type": medical_record.diabetes_type,
                                "blood_pressure": medical_record.blood_pressure,
                                "pregnancy_week": str(medical_record.pregnancy_week),
                            }
                        )
                    else:
                        break
                objs = {"patient":patient_obj,"medical_records":medical_records}
                return JsonResponse({
                    'success': True,
                    "objs":objs

                })

            except Exception as e:
                print("Error :",e)
                return JsonResponse({'success': False, 'error': 'Error.'})
        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)}'})
@login_required
def patient_edit(request, patient_id):

    """Patient profile view"""
    patient = get_object_or_404(Patient, id=patient_id)


    profile_data = {
        'success':True,
        'id': patient.id,
        'first_name': patient.first_name,
        'last_name': patient.last_name,
        'phone_number': patient.phone_number,
        'country_code': patient.country_code,
        'email': patient.user.email if patient.user else None,
        'date_of_birth': patient.date_of_birth.strftime('%Y-%m-%d') if patient.date_of_birth else None,
        'gender': patient.gender,
        'age': patient.age,
        'address': patient.address,
        'profile_picture': patient.profile_picture.url if patient.profile_picture else None,
        'identifier': patient.identifier,
        'biography': patient.biography,
        'status': 'active',  # Patient model doesn't have status field
    }
    print(profile_data)
    return JsonResponse({
            'success': True,
            'profile_data': profile_data
        })

from django.db import transaction



from django.db import transaction
from django.http import JsonResponse
from django.core.exceptions import ValidationError
from datetime import datetime
from .models import Patient, MedicalRecord
import logging

logger = logging.getLogger(__name__)


@login_required
@transaction.atomic
def update_patient(request):
    if request.method != 'POST':
        return JsonResponse({
            'success': False,
            'error': 'Only POST method is allowed'
        }, status=405)

    try:
        # 1. دریافت و اعتبارسنجی patient_id
        patient_id = request.POST.get('patient_id')
        if not patient_id:
            return JsonResponse({
                'success': False,
                'error': 'Patient ID is required'
            }, status=400)

        # 2. دریافت شیء بیمار
        try:
            patient = Patient.objects.get(id=patient_id)
        except Patient.DoesNotExist:
            return JsonResponse({
                'success': False,
                'error': 'Patient not found'
            }, status=404)

        # 3. به‌روزرسانی اطلاعات پایه بیمار
        patient.first_name = request.POST.get('first_name', patient.first_name)
        patient.last_name = request.POST.get('last_name', patient.last_name)

        # اعتبارسنجی سن
        try:
            age = int(request.POST.get('age', patient.age))
            if age < 0 or age > 150:
                raise ValidationError('Age must be between 0 and 150')
            patient.age = age
        except (ValueError, TypeError):
            pass

        # اعتبارسنجی جنسیت
        gender = request.POST.get('gender', patient.gender)
        if gender in dict(Patient.GENDER):
            patient.gender = gender

        # اطلاعات تماس
        patient.phone_number = request.POST.get('phone_number', patient.phone_number)
        patient.country_code = request.POST.get('country_code', patient.country_code)

        # سایر اطلاعات
        patient.address = request.POST.get('address', patient.address)
        patient.biography = request.POST.get('biography', patient.biography)

        # 4. مدیریت تصویر پروفایل
        if 'profile_picture' in request.FILES:
            patient.profile_picture = request.FILES['profile_picture']

        patient.save()

        # 5. مدیریت پرونده‌های پزشکی - ابتدا همه پرونده‌های قبلی را حذف می‌کنیم
        MedicalRecord.objects.filter(patient=patient).delete()

        # 6. ایجاد پرونده‌های پزشکی جدید بر اساس داده‌های ارسالی
        i = 0
        created_records = 0
        flags = []
        while True:
            record_type = request.POST.get(f'medical_records[{i}][record_type]')
            if not record_type :
                break  # وقتی دیگر رکوردی وجود ندارد، حلقه را متوقف کنید
            if record_type in flags:
                i += 1
                continue
            flags.append(record_type)
            try:

                record = MedicalRecord(patient=patient, record_type=record_type)

                # مدیریت تاریخ تشخیص
                diagnosis_date_str = request.POST.get(f'medical_records[{i}][diagnosis_date]')
                if diagnosis_date_str:
                    try:
                        record.diagnosis_date = datetime.strptime(diagnosis_date_str, '%Y-%m-%d').date()
                    except ValueError:
                        record.diagnosis_date = None

                # سایر فیلدها
                record.medications = request.POST.get(f'medical_records[{i}][drugs]', '')
                record.description = request.POST.get(f'medical_records[{i}][description]', '')
                record.status = request.POST.get(f'medical_records[{i}][status]', 'active')

                # فیلدهای خاص بر اساس نوع پرونده
                if record_type == 'diabetes':
                    record.diabetes_type = request.POST.get(f'medical_records[{i}][diabetes_type]', '')

                if record_type == 'hypertension':
                    record.blood_pressure = request.POST.get(f'medical_records[{i}][hypertension_level]', '')

                if record_type == 'pregnancy':
                    try:
                        record.pregnancy_week = int(request.POST.get(f'medical_records[{i}][pregnancy_weeks]', 0))
                    except (ValueError, TypeError):
                        record.pregnancy_week = 0

                record.save()
                created_records += 1
            except Exception as e:
                logger.error(f"Error creating medical record {i}: {str(e)}")

            i += 1

        # 7. پاسخ موفقیت‌آمیز
        return JsonResponse({
            'success': True,
            'message': 'Patient information updated successfully',
            'patient_id': patient.id,
            'created_records': created_records
        })

    except Exception as e:
        logger.exception("Error in update_patient")
        return JsonResponse({
            'success': False,
            'error': 'An error occurred while updating patient',
            'details': str(e) if settings.DEBUG else None
        }, status=500)


@login_required
def get_patient_medical_records(request, patient_id):
    """Get all medical records for a patient"""
    try:
        patient = get_object_or_404(Patient, id=patient_id)
        medical_records = MedicalRecord.objects.filter(patient=patient)

        records_data = []
        for record in medical_records:
            records_data.append({
                "id": str(record.id),
                "record_type": record.record_type,
                "diagnosis_date": record.diagnosis_date.strftime('%Y-%m-%d') if record.diagnosis_date else None,
                "medications": record.medications,
                "description": record.description,
                "status": record.status,
                "diabetes_type": record.diabetes_type,
                "blood_pressure": record.blood_pressure,
                "pregnancy_week": record.pregnancy_week,
            })

        return JsonResponse({
            'success': True,
            'medical_records': records_data
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


@login_required
def delete_medical_record(request, record_id):
    """Delete a medical record"""
    if request.method == 'DELETE':
        try:
            record = get_object_or_404(MedicalRecord, id=record_id)
            record.delete()
            return JsonResponse({'success': True})
        except Exception as e:
            return JsonResponse({'success': False, 'error': str(e)})
    return JsonResponse({'success': False, 'error': 'Invalid request method'})

class ExaminationView(View):
    template_name = 'core/examination.html'

    def get(self, request: HttpRequest, pk: int):
        reservation = Reservation.objects.get(pk=pk)

        context = {
            'reservation': reservation,
        }

        return render(request, self.template_name, context)
@login_required
def all_patient(request):
    patient_list = Patient.objects.all().order_by('id')
    patients = []
    for patient in patient_list:
        patients.append({
            'id': patient.id,
            'name': patient.get_full_name(),
            'wallet': patient.wallet,
            'phone_number': patient.phone_number,
            'country_code': patient.country_code,
        })
    results={"patients":patients}
    # print("results=",results)
    return JsonResponse({'success': True, 'results': results})
@login_required
def times_reservations(request, reservation_date,doctor_id,technician_dates):
    """
    View to get all reservations for a specific patient
    """
    patient = get_object_or_404(Patient, pk=pk)
    reservations = Reservation.objects.filter(patient=patient).order_by('-reservation_date')

    reservations_data = []
    for reservation in reservations:
        # Get image count for this reservation
        image_count = PatientImage.objects.filter(reservation=reservation).count()

        reservations_data.append({
            'id': reservation.id,
            'reservation_date': reservation.reservation_date.strftime('%Y-%m-%d %H:%M'),
            'service_name': reservation.service.name if reservation.service else 'N/A',
            'doctor_name': f"{reservation.doctor.first_name} {reservation.doctor.last_name}" if reservation.doctor else None,
            'technician_name': f"{reservation.technician.first_name} {reservation.technician.last_name}" if reservation.technician else None,
            'status': reservation.status,
            'notes': reservation.notes,
            'has_images': image_count > 0,
            'image_count': image_count
        })

    return JsonResponse({'reservations': reservations_data})


@login_required
def patient_reservations(request, pk):
    """
    View to get all reservations for a specific patient
    """
    try:
        categories = Category.objects.all()
        categories_data = []
        for cat in categories:
            quantity = 0
            warehouse = WarehouseItem.objects.filter(category=cat)
            for item in warehouse:
                quantity += item.quantity
                unit_price = item.unit_price
                categories_data.append(
                    {
                        'category_id': cat.id,
                        'id': item.id,
                        'name': cat.name,
                        'quantity': quantity,
                        'unit_price': unit_price}
                )
        patient = get_object_or_404(Patient, pk=pk)

        reservations = Reservation.objects.filter(patient=patient).order_by('-reservation_date')

        reservations_data = []
        for reservation in reservations:
            # Get image count for this reservation
            image_count = PatientImage.objects.filter(reservation=reservation).count()
            tecs = []
            for tec in reservation.technician.all():
                tecs.append({'id':tec.id,'name':tec.get_full_name()})
            reservations_data.append({
                'id': reservation.id,
                'patient_id': reservation.patient.id,
                'patient_name': reservation.patient.get_full_name(),
                'patient_phone': reservation.patient.phone_number,
                'country_code': reservation.patient.country_code,
                'reservation_date': reservation.reservation_date.strftime('%Y-%m-%d')  if reservation.reservation_date else None,
                'reservation_time': reservation.reservation_time.strftime('%H:%M')  if reservation.reservation_time else None,
                'service_id': reservation.service.id if reservation.service else None,
                'service_name': reservation.service.name if reservation.service else None,
                'doctor_id': reservation.doctor.id if reservation.doctor else None,
                'doctor_name': f"{reservation.doctor.get_full_name()}" if reservation.doctor else None,
                'technicians': tecs,
                'deposit': reservation.deposit,
                'status':reservation.status if reservation.status else '',
                'hours_duration':float(reservation.hours_duration) if reservation.hours_duration else 0,
                'minutes_duration':float(reservation.minutes_duration) if reservation.minutes_duration else 0,
                'patient_deposit':float(reservation.deposit) if reservation.deposit else 0,
                'patient_price': float(reservation.paient_price) if reservation.paient_price else 0,
                'doctor_price': float(reservation.doctor_price) if reservation.doctor_price else 0,
                'technician_price': float(reservation.technician_price) if reservation.technician_price else 0,
                'notes': reservation.notes,
                'has_images': image_count > 0,
                'image_count': image_count,
                'warehouse_items': categories_data
            })
    except Exception as e:
        print("error=",e)

    return JsonResponse({'reservations': reservations_data})


@login_required
def reservation_images(request, pk):
    """
    View to get all images for a specific reservation
    """
    reservation = get_object_or_404(Reservation, pk=pk)
    images = PatientImage.objects.filter(reservation=reservation).order_by('created_at')

    images_data = []
    for image in images:
        images_data.append({
            'id': image.id,
            'image_url': image.image.url,
            'image_type': image.image_type,
            'description': image.description,
            'created_at': image.created_at.strftime('%Y-%m-%d %H:%M')
        })

    return JsonResponse({'images': images_data})


@login_required
@require_POST
def delete_reservation(request, pk):
    """
    View to delete a reservation
    """
    reservation = get_object_or_404(Reservation, pk=pk)
    # Check if the user has permission to delete the reservation
    # (depending on your permission logic)

    # Delete the reservation
    reservation.delete()

    return JsonResponse({'success': True, 'message': 'رزرو با موفقیت حذف شد'})


@login_required
@require_POST
def update_patient_status(request, pk):
    """
    View to update the status of patient's latest reservation
    """
    patient = get_object_or_404(Patient, pk=pk)
    status = request.POST.get('status')

    valid_statuses = ['scheduled', 'confirmed', 'paied', 'technician-confirmed','technician-reject', 'send-to-doctor','doctor-confirmed','doctor-reject', 'completed', 'cancelled']
    if status not in valid_statuses:
        return JsonResponse({'success': False, 'message': 'Error'}, status=400)

    # Update the status of the latest reservation if exists
    latest_reservation = Reservation.objects.filter(patient=patient).order_by('-reservation_date').first()
    if not latest_reservation:
        return JsonResponse({'success': False, 'message': 'No Found '}, status=404)

    # Update reservation status
    latest_reservation.status = status
    latest_reservation.save()

    # Get status text in Persian
    status_text_map = {
        'scheduled': 'scheduled',
        'confirmed': 'confirmed',
        'paied': 'Payed',
        'technician-confirmed':'technician-confirmed',
        'technician-reject':'technician-reject',
        'doctor-confirmed':'doctor-confirmed',
        'send-to-doctor':'send-to-doctor',
        'doctor-reject':'doctor-reject',
        'completed': 'completed',
        'cancelled': 'cancelled'
    }
    status_text = status_text_map.get(status, status)

    return JsonResponse({
        'success': True,
        'message': f'وضعیت آخرین رزرو بیمار با موفقیت به {status_text} تغییر کرد',
        'latest_reservation_status': status
    })

# Patient Views
class PatientListView(ListView):

    model = Patient
    template_name = 'patient/user-list.html'
    context_object_name = 'patients'
    paginate_by = 10

    def get_queryset(self):
        print("in get_queryset")
        queryset = Patient.objects.all().prefetch_related(
            Prefetch(
                'patients_reservation',
                queryset=Reservation.objects.order_by('-reservation_date'),
                to_attr='ordered_reservations'
            )
        )


        # اعمال فیلترهای جستجو
        filter_type = self.request.GET.get('filterTypePatient')
        search_query = self.request.GET.get('searchQueryPatient', '').strip()
        status_filter = self.request.GET.get('statusFilter')
        reservation_status_filter = self.request.GET.get('reservationStatusFilter')
        date_filter = self.request.GET.get('dateFilter')
        start_date = self.request.GET.get('startDate')
        end_date = self.request.GET.get('endDate')
        sort_by = self.request.GET.get('sortBy', 'id_desc')

        # جستجوی عمومی
        general_search = self.request.GET.get('searchInput', '').strip()
        if general_search:
            queryset = queryset.filter(
                Q(first_name__icontains=general_search) |
                Q(last_name__icontains=general_search) |
                Q(phone_number__icontains=general_search)
            )

        # جستجوی خاص
        if filter_type and search_query:
            if filter_type == 'first_name':
                queryset = queryset.filter(
                    Q(first_name__icontains=search_query) |
                    Q(last_name__icontains=search_query)
                )
            elif filter_type == 'phone_number':
                queryset = queryset.filter(phone_number__icontains=search_query)

        # فیلتر وضعیت بیمار
        if status_filter:
            if status_filter == 'Active':
                queryset = queryset.filter(status='active')
            elif status_filter == 'Inactive':
                queryset = queryset.filter(status='inactive')

        # فیلتر بیماران بدون رزرو
        no_reservation_filter = self.request.GET.get('noReservationFilter')
        if no_reservation_filter == 'true':
            queryset = queryset.filter(patients_reservation__isnull=True)

        # فیلتر بر اساس وضعیت آخرین رزرو
        if reservation_status_filter:
            # ابتدا بیماران با رزرو را پیدا می‌کنیم
            patient_ids_with_status = []
            for patient in queryset:
                if hasattr(patient, 'ordered_reservations') and patient.ordered_reservations:
                    latest_reservation = patient.ordered_reservations[0]
                    if latest_reservation.status == reservation_status_filter:
                        patient_ids_with_status.append(patient.id)

            queryset = queryset.filter(id__in=patient_ids_with_status)

        # فیلتر تاریخی
        if date_filter:
            today = timezone.now().date()
            if date_filter == 'today':
                start_date = today
                end_date = today
            elif date_filter == 'week':
                start_date = today - timedelta(days=7)
                end_date = today
            elif date_filter == 'month':
                start_date = today - timedelta(days=30)
                end_date = today

        # فیلتر محدوده تاریخی سفارشی
        if start_date and end_date:
            try:
                start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
                end_date = datetime.strptime(end_date, '%Y-%m-%d').date()

                # پیدا کردن بیماران با رزرو در محدوده تاریخی
                patient_ids_in_range = []
                for patient in queryset:
                    if hasattr(patient, 'ordered_reservations') and patient.ordered_reservations:
                        latest_reservation = patient.ordered_reservations[0]
                        reservation_date = latest_reservation.reservation_date.date()
                        if start_date <= reservation_date <= end_date:
                            patient_ids_in_range.append(patient.id)

                queryset = queryset.filter(id__in=patient_ids_in_range)
            except ValueError:
                pass

        # مرتب‌سازی
        if sort_by == 'id_asc':
            queryset = queryset.order_by('id')
        elif sort_by == 'id_desc':
            queryset = queryset.order_by('-id')
        elif sort_by == 'name_asc':
            queryset = queryset.order_by('first_name', 'last_name')
        elif sort_by == 'name_desc':
            queryset = queryset.order_by('-first_name', '-last_name')
        # مرتب‌سازی بر اساس تاریخ آخرین رزرو در JavaScript انجام می‌شود

        print("in get_queryset2 queryset=",queryset)
        return queryset

    def get_context_data(self, **kwargs):
        print("in get_context_data")
        context = super().get_context_data(**kwargs)

        # برای هر بیمار، اطلاعات آخرین رزرو را اضافه می‌کنیم
        for patient in context['page_obj']:
            if hasattr(patient, 'ordered_reservations') and patient.ordered_reservations:
                latest_reservation = patient.ordered_reservations[0]
                patient.latest_reservation_date = latest_reservation.reservation_date
                patient.latest_reservation_status = latest_reservation.status
                patient.has_reservations = True
            else:
                patient.latest_reservation_date = None
                patient.latest_reservation_status = None
                patient.has_reservations = False

        return context

    def render_to_response(self, context, **response_kwargs):
        response = super().render_to_response(context, **response_kwargs)
        if self.request.GET.get('refresh') == '1':
            response['Cache-Control'] = 'no-store'
            return response
        # چک کردن نوع درخواست (HTML یا JSON)
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest' or self.request.GET.get('format') == 'json':
            # خروجی JSON
            patients_data = []

            for patient in context['page_obj']:
                # print("patient.wallet=",patient.wallet)
                # ساخت دیتای بیمار برای JSON
                patient_data = {
                    'id': patient.id,
                    'first_name': patient.first_name,
                    'last_name': patient.last_name,
                    'full_name': patient.get_full_name(),
                    'wallet': patient.wallet,
                    'phone_number': patient.phone_number,
                    'country_code': patient.country_code,
                    'status': getattr(patient, 'status', 'active'),
                    'has_profile_picture': bool(patient.profile_picture),
                    'profile_picture_url': patient.profile_picture.url if patient.profile_picture else None,
                    'short_name': patient.get_short_name(),
                }

                # اضافه کردن اطلاعات آخرین رزرو
                if hasattr(patient, 'has_reservations') and patient.has_reservations:
                    patient_data.update({
                        'has_reservations': True,
                        'latest_reservation_date': patient.latest_reservation_date.strftime(
                            '%Y-%m-%d') if patient.latest_reservation_date else None,
                        'latest_reservation_date_formatted': patient.latest_reservation_date.strftime(
                            '%Y/%m/%d') if patient.latest_reservation_date else None,
                        'latest_reservation_status': patient.latest_reservation_status,
                        'latest_reservation_timestamp': patient.latest_reservation_date if patient.latest_reservation_date else None
                    })
                else:
                    patient_data.update({
                        'has_reservations': False,
                        'latest_reservation_date': None,
                        'latest_reservation_date_formatted': None,
                        'latest_reservation_status': None,
                        'latest_reservation_timestamp': 0
                    })

                patients_data.append(patient_data)

            # پاسخ JSON
            return JsonResponse({
                'patients': patients_data,
                'count': context['paginator'].count,
                'num_pages': context['paginator'].num_pages,
                'current_page': context['page_obj'].number,
                'has_next': context['page_obj'].has_next(),
                'has_prev': context['page_obj'].has_previous(),
                'next_page_number': context['page_obj'].next_page_number() if context['page_obj'].has_next() else None,
                'prev_page_number': context['page_obj'].previous_page_number() if context[
                    'page_obj'].has_previous() else None
            })

        # خروجی HTML (پیش‌فرض)
        return super().render_to_response(context, **response_kwargs)

@method_decorator(login_required, name='dispatch')
class PatientDetailView(DetailView):
    model = Patient
    template_name = 'patients/patient_detail.html'
    context_object_name = 'patient'

    def get_object(self, queryset=None):
        obj = super().get_object(queryset=queryset)
        # بررسی مجوز دسترسی (مثال)

        if not self.request.user.is_staff and self.request.user != obj.user:
            print("Error")
            return
            # raise PermissionDenied
        return obj
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['medical_records'] = self.object.medical_records.all()
        context['reservations'] = self.object.reservations.all().order_by('-reservation_date')
        context['images'] = self.object.images.all()
        return context


# @method_decorator(login_required, name='dispatch')
# class PatientCreateView(CreateView):
#     model = Patient
#     form_class = PatientForm
#     template_name = 'patient/helper_service/patient_modal_add.html'
#
#     def form_valid(self, form):
#         patient = form.save()
#         if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
#             return JsonResponse({
#                 'success': True,
#                 'patient': {
#                     'id': patient.id,
#                     'first_name': patient.first_name,
#                     'last_name': patient.last_name,
#                     'phone_number': patient.phone_number,
#                 }
#             })
#         return super().form_valid(form)
#
#     def form_invalid(self, form):
#         if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
#             return JsonResponse({
#                 'success': False,
#                 'error': form.errors.as_json()
#             }, status=400)
#         return super().form_invalid(form)
#
#     def get_success_url(self):
#         return reverse_lazy('patient:patients')
from django.views import View
import json
from .models import generate_random_id
import re
from datetime import datetime
from django.core.exceptions import ValidationError



@method_decorator(login_required, name='dispatch')
class PatientUpdateView(UpdateView):
    model = Patient
    form_class = PatientForm
    template_name = 'patients/patient_form.html'

    def get_success_url(self):
        return reverse_lazy('patient:patient-detail', kwargs={'pk': self.object.pk})

    def form_valid(self, form):
        messages.success(self.request, "Success")
        return super().form_valid(form)


@method_decorator(login_required, name='dispatch')
class PatientDeleteView(DeleteView):
    model = Patient
    template_name = 'patients/patient_confirm_delete.html'

    def get_success_url(self):
        return reverse_lazy('patient:patients')

    def delete(self, request, *args, **kwargs):
        messages.success(request, "بیمار با موفقیت حذف شد")
        return super().delete(request, *args, **kwargs)


# Patient Image Views
@login_required
def add_patient_image(request, patient_id):
    patient = get_object_or_404(Patient, id=patient_id)

    if request.method == 'POST':
        form = PatientImageForm(request.POST, request.FILES)
        if form.is_valid():
            image = form.save(commit=False)
            image.patient = patient
            image.save()
            messages.success(request, "تصویر با موفقیت اضافه شد")
            return redirect('patient:patient-detail', pk=patient.id)
    else:
        form = PatientImageForm()

    return render(request, 'patients/add_image.html', {
        'form': form,
        'patient': patient
    })


@login_required
def delete_patient_image(request, image_id):
    image = get_object_or_404(PatientImage, id=image_id)
    patient_id = image.patient.id
    image.delete()
    messages.success(request, "تصویر با موفقیت حذف شد")
    return redirect('patient:patient-detail', pk=patient_id)


# Medical Record Views
@method_decorator(login_required, name='dispatch')
class MedicalRecordCreateView(CreateView):
    model = MedicalRecord
    form_class = MedicalRecordForm
    template_name = 'patients/medical_record_form.html'

    def dispatch(self, request, *args, **kwargs):
        self.patient = get_object_or_404(Patient, pk=self.kwargs.get('patient_id'))
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['patient'] = self.patient
        return context

    def form_valid(self, form):
        form.instance.patient = self.patient
        messages.success(self.request, "سابقه پزشکی با موفقیت ثبت شد")
        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy('patient:patient-detail', kwargs={'pk': self.patient.pk})


@method_decorator(login_required, name='dispatch')
class MedicalRecordUpdateView(UpdateView):
    model = MedicalRecord
    form_class = MedicalRecordForm
    template_name = 'patients/medical_record_form.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['patient'] = self.object.patient
        return context

    def form_valid(self, form):
        messages.success(self.request, "سابقه پزشکی با موفقیت بروزرسانی شد")
        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy('patient:patient-detail', kwargs={'pk': self.object.patient.pk})


@method_decorator(login_required, name='dispatch')
class MedicalRecordDeleteView(DeleteView):
    model = MedicalRecord
    template_name = 'patients/medical_record_confirm_delete.html'

    def get_success_url(self):
        return reverse_lazy('patient:patient-detail', kwargs={'pk': self.object.patient.pk})

    def delete(self, request, *args, **kwargs):
        messages.success(request, "سابقه پزشکی با موفقیت حذف شد")
        return super().delete(request, *args, **kwargs)


# Reservation Views
class ReservationListView(ListView):
    model = Reservation
    template_name = 'reservations/reservation_list.html'
    context_object_name = 'reservations'
    paginate_by = 10

    def get_queryset(self):
        status = self.request.GET.get('status')
        if status:
            return Reservation.objects.filter(status=status).order_by('-reservation_date')
        return Reservation.objects.all().order_by('-reservation_date')

def ajax_login_required(view_func):
    def _wrapped_view(request, *args, **kwargs):
        if not request.user.is_authenticated:
            if request.headers.get('x-requested-with') == 'XMLHttpRequest':
                return JsonResponse({'success': False, 'error': 'شما وارد نشده‌اید'}, status=401)
        return view_func(request, *args, **kwargs)
    return _wrapped_view
# @login_required
@ajax_login_required
@require_http_methods(["POST"])
def doctors_by_service(request):
    try:
        doctors = Doctor.objects.all()

        doctor_list = [{
            'id': doctor.id,
            'first_name': doctor.first_name,
            'last_name': doctor.last_name,
            'specialty': doctor.specialty,
        } for doctor in doctors]

        return JsonResponse({'success': True, 'doctors': doctor_list})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)}, status=500)

@method_decorator(login_required, name='dispatch')
class ReservationDetailView(DetailView):
    model = Reservation
    # template_name = 'reservation/reservation_detail.html'
    template_name = 'patient/user-list.html'
    context_object_name = 'reservation'


@method_decorator(login_required, name='dispatch')
# @method_decorator(csrf_exempt, name='dispatch')  # اگر CSRF token را از header می‌گیری، این را بردار و از csrf_protect استفاده کن
class ReservationCreateNewJSONView(View):
    def post(self, request, *args, **kwargs):
        try:
            user = request.user
            exchange = ExchangeRate.objects.last()
            data = json.loads(request.body)

            # اعتبارسنجی داده‌های ضروری
            if not data.get('patient_id'):
                return JsonResponse({'success': False, 'error': 'The patient must be selected'}, status=400)
            if not data.get('service_id'):
                return JsonResponse({'success': False, 'error': 'The service must be selected'}, status=400)

            # دریافت بیمار و سرویس (ضروری)
            patient = Patient.objects.get(id=data['patient_id'])
            service = Service.objects.get(id=data['service_id'])

            # مدیریت فیلدهای اختیاری با مقادیر پیش‌فرض
            leader = User.objects.get(id=data['leader_id']) if data.get('leader_id') else None
            leader_price = Decimal(data['leader_price']) if data.get('leader_price') else 0.0
            doctor = Doctor.objects.get(id=data['doctor_id']) if data.get('doctor_id') else None

            technician_ids = [int(id_) for id_ in data.get('technician_ids', []) if id_]
            technicians = Technician.objects.filter(id__in=technician_ids) if technician_ids else []


            # مدیریت تاریخ رزرو (اختیاری)
            reservation_date = data.get('reservation_date')
            if reservation_date:
                try:
                    # اعتبارسنجی فرمت تاریخ
                    datetime.strptime(reservation_date, '%Y-%m-%d')
                    if Reservation.objects.filter(patient=patient, service=service,
                                                  reservation_date=reservation_date).exists():
                        return JsonResponse(
                            {'success': False,
                             'error':'Sorry!This service is reserved in that date by this patient' },
                            status=400)
                except ValueError:
                    return JsonResponse(
                        {'success': False, 'error': 'Error'},
                        status=400)
            else:
                reservation_date = None

            try:
                deposit = float(data['deposit']) if data.get('deposit') not in [None, ''] else 0.0
                discount = float(data['discount']) if data.get('discount') not in [None, ''] else 0.0
                hours_duration = float(data['hours_duration']) if data.get('hours_duration') not in [None, ''] else 0.0
                minutes_duration = float(data['minutes_duration']) if data.get('minutes_duration') not in [None,
                                                                                                           ''] else 0.0
            except ValueError:
                return JsonResponse({'success': False, 'error': 'مقدار عددی نامعتبر'}, status=400)

                # مدیریت نرخ ارز
            exchange = ExchangeRate.objects.last()
            exchange_rate = float(exchange.rate) if exchange else 1.0
            currency_type = data.get('currency_type', 'dollar')

            if currency_type == "dinar":
                deposit = deposit / exchange_rate
                discount = discount / exchange_rate

            # مدیریت کیف پول بیمار
            old_patient_wallet = patient.wallet
            patient.wallet = max(Decimal(0), old_patient_wallet - Decimal(str(deposit)))
            patient.save()
            try:
                send_wallet_notification(
                    recipient_type='patient',
                    person=patient,
                    amount=deposit,
                    wallet_after=patient.wallet,
                    phone=patient.country_code + patient.phone_number
                )
            except Exception as e:
                print(e)
            wallet_change = old_patient_wallet - patient.wallet

            # ایجاد رزرو با تمام فیلدهای اختیاری
            reservation = Reservation.objects.create(
                patient=patient,
                service=service,
                doctor=doctor,
                leader=leader,
                leader_price=leader_price,
                deposit=deposit,
                discount=discount,
                status=data.get('status', 'confirmed'),
                reservation_date=reservation_date,
                hours_duration=hours_duration,
                minutes_duration=minutes_duration,
                notes=data.get('notes', ''),
                expense_type=currency_type,
                created_by=user
            )

            if technicians:
                reservation.technician.set(technicians)

            # ایجاد لاگ
            ReservationChangeLog.objects.create(
                reservation=reservation,
                action_type='create',
                source_model='Reservation',
                new_data=json.dumps({
                    'patient_id': patient.id,
                    'service_id': service.id,
                    'doctor_id': doctor.id if doctor else None,
                    'leader_id': leader.id if leader else None,
                    'technician_ids': technician_ids,
                    'deposit': deposit,
                    'discount': discount,
                    'status': data.get('status', 'confirmed'),
                    'reservation_date': reservation_date,
                    'wallet_change': float(wallet_change)
                }, ensure_ascii=False),
                changed_by=user,
                description=f"New reservation created for {patient.get_full_name()}"
            )

            # ایجاد پرونده پزشکی
            # MedicalRecord.objects.create(
            #     reservation=reservation,
            #     created_by=user
            # )
            try:
                hours_duration = int(reservation.hours_duration) if reservation.hours_duration else ''
                minutes_duration = int(reservation.minutes_duration) if reservation.minutes_duration else ''
                time_duration = str(hours_duration)+":"+str(minutes_duration) if hours_duration else ''
                deposit = str(reservation.deposit) if reservation.deposit else '0'
                print("time_duration=",time_duration)
                message_template_obj = MessageWhatsappTemplate.objects.get(message_type='reservation_created')
                print("message_template_obj.content=",message_template_obj.content)
                template = Template(message_template_obj.content)
                print("template=",template)
                context_data = {
                    'full_name': patient.get_full_name(),
                    'service_name': reservation.service.name if reservation  and reservation.service else '',
                    'reservation_date': str(reservation.reservation_date)+" "+time_duration if reservation else '',
                    'deposit':deposit,
                }
                print("context_data=",context_data)

                context = Context(context_data)
                personalized_message = template.render(context)
                print("personalized_message=",personalized_message)
                phone = patient.country_code+patient.phone_number
                # time.sleep(2)
                success = send_whatsapp(phone, personalized_message)
            except Exception as e:
                print(e)
            return JsonResponse({
                'success': True,
                'reservation_id': reservation.id,
                'message': 'Reservation created successfully'
            })

        except Patient.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Patient not found'}, status=400)
        except Service.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Service not found'}, status=400)
        except Doctor.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Doctor not found'}, status=400)
        except User.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Leader not found'}, status=400)
        except Technician.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Technician not found'}, status=400)
        except Exception as e:
            import traceback
            traceback.print_exc()
            return JsonResponse({'success': False, 'error': str(e)}, status=500)


@method_decorator(login_required, name='dispatch')
class ReservationCreateView(CreateView):

    model = Reservation
    form_class = ReservationForm
    template_name = 'patient/helper_service/reservation_modal_add.html'

    def get_success_url(self):
        return reverse_lazy('patient:reservation-list')

    def dispatch(self, request, *args, **kwargs):
        self.patient_id = self.kwargs.get('patient_id')
        if self.patient_id:
            self.patient = get_object_or_404(Patient, pk=self.patient_id)
        return super().dispatch(request, *args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        if hasattr(self, 'patient'):
            kwargs.update({'patient': self.patient})
        return kwargs

    def get_initial(self):
        initial = super().get_initial()
        if hasattr(self, 'patient'):
            initial['patient'] = self.patient
        return initial

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        reservation = form.save()

        if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({
                'success': True,
                'reservation_id': reservation.id,
                'appointment_date': reservation.appointment_date.strftime('%Y-%m-%d'),
                'appointment_time': reservation.appointment_time.strftime('%H:%M'),
            })
        messages.success(self.request, "نوبت با موفقیت ثبت شد")
        return super().form_valid(form)

    def form_invalid(self, form):
        if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'error': form.errors.as_json()
            }, status=400)
        return super().form_invalid(form)
@method_decorator(login_required, name='dispatch')
class ReservationUpdateView(UpdateView):
    model = Reservation
    form_class = ReservationForm
    template_name = 'reservations/reservation_form.html'

    def get_success_url(self):
        return reverse_lazy('patient:reservation-detail', kwargs={'pk': self.object.pk})

    def form_valid(self, form):
        messages.success(self.request, "نوبت با موفقیت بروزرسانی شد")
        return super().form_valid(form)


@method_decorator(login_required, name='dispatch')
class ReservationDeleteView(DeleteView):
    model = Reservation
    template_name = 'reservations/reservation_confirm_delete.html'

    def get_success_url(self):
        return reverse_lazy('patient:reservation-list')

    def delete(self, request, *args, **kwargs):
        messages.success(request, "نوبت با موفقیت حذف شد")
        return super().delete(request, *args, **kwargs)


@login_required
def change_reservation_status(request, pk, status):
    reservation = get_object_or_404(Reservation, pk=pk)
    if status in [choice[0] for choice in Reservation._meta.get_field('status').choices]:
        reservation.status = status
        reservation.save()
        messages.success(request,
                         f"وضعیت نوبت به {dict(Reservation._meta.get_field('status').choices)[status]} تغییر یافت")
    return redirect('patient:reservation-detail', pk=pk)


# API Endpoints
@login_required
def check_availability(request):
    doctor_id = request.GET.get('doctor_id')
    date_str = request.GET.get('date')
    time_str = request.GET.get('time')

    if not (doctor_id and date_str and time_str):
        return JsonResponse({'available': False, 'error': 'Missing parameters'})

    try:
        from datetime import datetime, timedelta

        # تبدیل تاریخ و زمان به datetime
        date_format = '%Y-%m-%d'
        time_format = '%H:%M'

        date_obj = datetime.strptime(date_str, date_format).date()
        time_obj = datetime.strptime(time_str, time_format).time()

        reservation_datetime = datetime.combine(date_obj, time_obj)

        from .models import Doctor
        doctor = Doctor.objects.get(id=doctor_id)

        is_available = Reservation.is_slot_available(doctor, reservation_datetime)

        return JsonResponse({'available': is_available})
    except Exception as e:
        return JsonResponse({'available': False, 'error': str(e)})









from decimal import Decimal, InvalidOperation

from django.views import View

from .mixins import AccessLevelRequiredMixin
from core.models import PatientService, PatientServiceItem, Service
from doctor.models import Doctor, Technician
from django.http import HttpRequest , JsonResponse

class PatientAddServiceView(AccessLevelRequiredMixin, View):
    pass
class PatientServiceHistoryView(View):
    pass
class PatientEditView(AccessLevelRequiredMixin,View):
    pass
class PatientGalleryView(AccessLevelRequiredMixin, View):
    pass

