<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Helper\Helper;
use Illuminate\Support\Facades\Mail;
use App\Mail\AppointmentNotificationMail;
use App\Mail\AppointmentMail;
use App\Mail\AppointmentMailWithTemplate;
use App\Http\Response\Response;
use App\Models\Representative;
use App\Models\Patients;
use App\Models\Settings;
use App\Models\RelationShip;
use App\Models\Appointments;
use App\Models\Especiality;
use Illuminate\Support\Facades\DB;
use \Acaronlex\LaravelCalendar\Calendar;
use Throwable;
use App\Exceptions\GlobalException;
use Illuminate\Support\Carbon;
use App\Models\UserProfile;
use \DateTime;
use \DateTimeZone;
use App\Models\User;
use App\Models\RoleUser;
use App\Models\Currencies;
use App\Models\PaymentMethods;
use App\Models\Payments;
use Illuminate\Support\Facades\Auth;
use App\Helper\ClinicIdentityHelper;
use App\Exports\AppointmentExport;
use Maatwebsite\Excel\Facades\Excel;
use App\Models\MedicalService;
use App\Models\MedicalServiceSnapshot;



class AppointmentController extends Controller
{
    // Métodos para la integración con pagos



     /**
     * Procesa el pago y finaliza la creación de la cita
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function completePaymentIndividual(Request $request)
    {
        DB::beginTransaction();
        try {
            $data = $request->all();
            // Crear el pago asociado a esta cita
            $payment = new Payments();
            $payment->id = Helper::createId();
            $payment->especiality_id = $data['especiality'];
            $payment->users_id = $data['doctors'];
            $payment->payment_methods_id = $data['paymentMethods'];
            $payment->currencies_id = $data['currency'];
            $payment->amount = str_replace(',', '.', str_replace('.', '', $data['amount']));
          // $payment->amount = $data['amount'];
            $payment->appointment_id = $data['appointment_id']; // Asociar con la cita

            
            // Manejar pago electrónico
            $payment->is_electronic = isset($data['is_electronic']) ? true : false;
            
            // Si es pago electrónico, usar referencia proporcionada por el usuario
            if ($payment->is_electronic && isset($data['user_reference'])) {
                $payment->user_reference = $data['user_reference'];
                $payment->reference = $data['user_reference']; // Usar la misma referencia
            } else {
                // Si no es electrónico, generar referencia automática
                $payment->reference = substr(Helper::createReferenceForPayments($payment->users_id, $payment->amount), 0, 255);
            }
            
            $payment->description = $data['reason'];
            $payment->payer = $data['payer'];
            $payment->address_payer = $data['address_payer'];
            
            // Al crear un pago adicional
            if (isset($data['isAdditionalPayment']) && $data['isAdditionalPayment']) {
                $payment->parent_id = $data['parentPayment']->id;
            }
            
            $payment->save();

             // Save medical services
             if (isset($data['medical_services']) && is_array($data['medical_services'])) {
                // Primero eliminar relaciones existentes
                $payment->medicalServices()->detach();
                
                // Luego crear una relación por cada elemento del array (incluyendo duplicados)
                foreach ($data['medical_services'] as $serviceId) {
                    $medicalService = MedicalService::findOrFail($serviceId);
                    $medicalServiceAttributes = $medicalService->toArray();
                    $medicalServiceAttributes['id'] = md5(uniqid(rand(), true) . Helper::createId());
                    $medicalServiceSnapshot = MedicalServiceSnapshot::create($medicalServiceAttributes);
                    $payment->medicalServices()->attach($medicalServiceSnapshot->id);
                }
            }
            DB::commit();
            return redirect()->route("/admin/detail-payment", ['id' => $payment->id]);
        } catch (\Throwable $th) {
            DB::rollBack();
            throw new GlobalException($th->getMessage());
        }
    }

    public function paymentForAppointmentIndividual(Request $request, Appointments $appointment){
        try {
            try {
                
                if (!$appointment) {
                    $request->session()->flash('error', __('error-500.appointmentRequired'));
                    return redirect()->route('/admin/create-appointment');
                }
                
                // Obtener los datos necesarios para el formulario de pago
                $currencies = Currencies::all();
                $paymentMethods = PaymentMethods::all();
                $doctors = User::getAllDoctors();
                $optionsEspeciality = Especiality::getEspecialities();
                
                // Obtener datos del paciente seleccionado
                $patientId = $appointment->patients_id;
                $patient = Patients::find($patientId);
                
                // Obtener datos del doctor seleccionado
                $doctorId = $appointment->users_id;
                $doctor = User::find($doctorId);
                
                $payment = new Payments();
                
                // Obtener servicios médicos
                $medicalServices = MedicalService::all();
                
                return view('payment-for-appointment-individual', [
                    'appointmentData' => [
                        'id' => $appointment->id,
                        'patients_id' => $appointment->patients_id,
                        'users_id' => $appointment->users_id,
                        'date' => $appointment->date,
                        'reason' => $appointment->summary,
                        'especiality' => $appointment->especiality // Asegurar que existe
                    ],
                    'currencies' => $currencies,
                    'paymentMethods' => $paymentMethods,
                    'doctors' => $doctors,
                    'payment' => $payment,
                    'patient' => $patient,
                    'doctor' => $doctor,
                    'optionsEspeciality' => $optionsEspeciality,
                    'medicalServices' => $medicalServices
                ]);
            } catch (\Throwable $th) {
                throw new GlobalException($th->getMessage());
            }
        } catch (\Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }
    
    /**
     * Muestra el formulario de pago para una cita pendiente
     * @param Request $request
     * @return \Illuminate\Contracts\View\View
     */
    public function paymentForAppointment(Request $request)
    {
        try {
            // Obtener datos de la cita pendiente
            $appointmentData = session('pending_appointment');
            
            if (!$appointmentData) {
                $request->session()->flash('error', __('error-500.appointmentRequired'));
                return redirect()->route('/admin/create-appointment');
            }
            
            // Obtener los datos necesarios para el formulario de pago
            $currencies = Currencies::all();
            $paymentMethods = PaymentMethods::all();
            $doctors = User::getAllDoctors();
            $optionsEspeciality = Especiality::getEspecialities();
            
            // Obtener datos del paciente seleccionado
            $patientId = $appointmentData['patients_id'];
            $patient = Patients::find($patientId);
            
            // Obtener datos del doctor seleccionado
            $doctorId = $appointmentData['users_id'];
            $doctor = User::find($doctorId);
            
            $payment = new Payments();
            
            // Obtener servicios médicos
            $medicalServices = MedicalService::all();
            
            return view('payment-for-appointment', [
                'appointmentData' => [
                    'id' => $appointmentData['id'],
                    'patients_id' => $appointmentData['patients_id'],
                    'users_id' => $appointmentData['users_id'],
                    'date' => $appointmentData['date'],
                    'reason' => $appointmentData['summary'],
                    'especiality' => $appointmentData['especiality'] // Asegurar que existe
                ],
                'currencies' => $currencies,
                'paymentMethods' => $paymentMethods,
                'doctors' => $doctors,
                'payment' => $payment,
                'patient' => $patient,
                'doctor' => $doctor,
                'optionsEspeciality' => $optionsEspeciality,
                'medicalServices' => $medicalServices
            ]);
        } catch (\Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }


    /**
     * Crea una cita
     * @param array $appointmentData
     * @return Appointments
     */
    public function createAppointment($appointmentData){
            $appointment = new Appointments();
            $appointmentData['id'] = Helper::createId();
            $count = Appointments::count();
            $appointmentData['code'] = 'MED-' . ($count + 1);
            if(self::validateThereAppointment($appointmentData['date'],$appointmentData['users_id'])){
                throw new GlobalException(__('error-500.appointmentTimeRepeat'));
            }
            $appointment->fill($appointmentData);
            $appointment->save();
            return $appointment;
    }

    /**
     * @return Boolean
     */
    public static function validateThereAppointment($date,$users_id){
        $appointment = Appointments::where('date', $date)
        ->where('users_id', $users_id)
        ->where('active', 1)->first();
        return $appointment ? true : false;
    }
    
    /**
     * Procesa el pago y finaliza la creación de la cita
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function completeAppointmentWithPayment(Request $request)
    {
        //transacciones de mysql
        DB::beginTransaction();
        try {
            // Recuperar datos de la cita pendiente
            $appointmentData = session('pending_appointment');
            $appointmentTags = session('appointment_tags');

            if (!$appointmentData) {
                $request->session()->flash('error', __('error-500.appointmentDataNotFound'));
                return redirect()->route('/admin/create-appointment');
            }
            
            $data = $request->all();
            
            // Crear la cita primero
            $appointment = $this->createAppointment($appointmentData);
            
            // Guardar las etiquetas seleccionadas, si existen
            if (isset($appointmentTags) && is_array($appointmentTags)) {
                $appointment->tags()->sync($appointmentTags);
            }
            
            // Crear el pago asociado a esta cita
            $payment = new Payments();
            $payment->id = Helper::createId();
            $payment->especiality_id = $data['especiality'];
            $payment->users_id = $data['doctors'];
            $payment->payment_methods_id = $data['paymentMethods'];
            $payment->currencies_id = $data['currency'];
            $payment->amount = str_replace(',', '.', str_replace('.', '', $data['amount']));
          // $payment->amount = $data['amount'];
            $payment->appointment_id = $appointment->id; // Asociar con la cita

            
            // Manejar pago electrónico
            $payment->is_electronic = isset($data['is_electronic']) ? true : false;
            
            // Si es pago electrónico, usar referencia proporcionada por el usuario
            if ($payment->is_electronic && isset($data['user_reference'])) {
                $payment->user_reference = $data['user_reference'];
                $payment->reference = $data['user_reference']; // Usar la misma referencia
            } else {
                // Si no es electrónico, generar referencia automática
                $payment->reference = substr(Helper::createReferenceForPayments($payment->users_id, $payment->amount), 0, 255);
            }
            
            $payment->description = $data['reason'];
            $payment->payer = $data['payer'];
            $payment->address_payer = $data['address_payer'];
            
            // Al crear un pago adicional
            if (isset($data['isAdditionalPayment']) && $data['isAdditionalPayment']) {
                $payment->parent_id = $data['parentPayment']->id;
            }
            
            $payment->save();
            
            // Save medical services
            if (isset($data['medical_services']) && is_array($data['medical_services'])) {
                // Primero eliminar relaciones existentes
                $payment->medicalServices()->detach();
                
                // Luego crear una relación por cada elemento del array (incluyendo duplicados)
                foreach ($data['medical_services'] as $serviceId) {
                    $medicalService = MedicalService::findOrFail($serviceId);
                    $medicalServiceAttributes = $medicalService->toArray();
                    $medicalServiceAttributes['id'] = md5(uniqid(rand(), true) . Helper::createId());
                    $medicalServiceSnapshot = MedicalServiceSnapshot::create($medicalServiceAttributes);
                    $payment->medicalServices()->attach($medicalServiceSnapshot->id);
                }
            }
            
            // Enviar notificación por email
            $this->sendAppointmentNotification($appointment);
            
            // Limpiar la sesión
            session()->forget('pending_appointment');
            $request->session()->flash('success', __('common.appointmentWithPaymentSuccess'));
            DB::commit();
            return redirect()->route("/admin/detail-appointment", ['id' => $appointment->id]);
        } catch (\Throwable $th) {
            DB::rollBack();
            $request->session()->flash('error', $th->getMessage());
            return redirect()->back()->withInput($request->all());
        }
    }
    
    /**
     * Envía notificación por email para una cita
     * @param Appointments $model
     */
    private function sendAppointmentNotification($model)
    {
        $patient = $model->patient()->first();
        
        // Verificar si $model->date ya es un objeto DateTime
        if ($model->date instanceof DateTime) {
            $date = $model->date;
        } elseif ($model->date instanceof \Carbon\Carbon) {
            // Si es un objeto Carbon, conviértelo a DateTime
            $date = $model->date->toDateTime();
        } else {
            // Si es una cadena, crea un nuevo DateTime
            $date = new DateTime($model->date, new DateTimeZone(Settings::findConfigValue('TIME_ZONE')));
        }
        
        $dateStr = $date->format('d-m-Y');
        $hour = $date->format('g:i A');
        $dataToSend = [
            'hour' => $hour,
            'date' => $dateStr,
            'fullname' => $patient->firstname . ' ' . $patient->lastname,
            'contactNumber' => Settings::findConfigValue('CONTACT_PHONE_NUMBER'),
            'contactEmail' => Settings::findConfigValue('CONTACT_EMAIL'),
        ];
        
        $emails = [];
        if ($patient->age > 17) {
            if (isset($patient->email)) {
                array_push($emails, $patient->email);
            }
        } else {
            $emails = array_merge($emails, Patients::getEmailForRepresentatives($patient));
        }

        $this->dispatchEmailAppointmentWithTemplate($dataToSend, $emails, $model);
    }

    /**
     * Elimina una cita marcándola como cancelada
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function delete(Request $request){
        try{
            $response = [];
            if($request->ajax()){
                $model = Appointments::find($request->all()["id"]);
                // Cambiar el estado a Cancelada (3)
                $model->status = 3;
                $model->active = 0;
                $model->deleted = 1;
                $save = $model->save();
                $response =  [
                    "error"=>(!$save),
                    "status"=>"success",
                    "opstatus"=>0,
                    "message"=>"done"
                ];
                return response()->json($response);
            }else{
                return redirect()->route('/admin/login');
            }
        }catch (Throwable $th) {
            $response =  [
                "error"=>true,
                "status"=>"error",
                "opstatus"=>500,
                "message"=>$th->getMessage()
            ];
            return response()->json($response);
        }
    }

    /**
     * 
     */
    public function detail(Request $request){
       try{
        $model = Appointments::find($request->all()["id"]);
        if((!isset($model)) || $model->deleted == 1) return redirect()->route("/admin/view-appointments");
        if($model === null)
                throw new GlobalException(__("error-500.messageNoSearch"));
        return view("detail-appointment",[
            "model"=>$model
        ]);
       }catch(Throwable $th){
        throw new GlobalException($th->getMessage());
       }
    }


    public function rememberAppointment(Request $request){
        $model = Appointments::find($request->all()["id"]);
        if($model === null)
                throw new GlobalException(__("error-500.messageNoSearch"));
        $sendEmail = function($model){
            $patient = $model->patient()->first();
            $date = new DateTime($model->date, new DateTimeZone(Settings::findConfigValue("TIME_ZONE")));
            $dateStr = $date->format('d-m-Y');
            $hour = $date->format('g:i A');
            $dataToSend = [
                'hour' => $hour,
                'date' => $dateStr,
                'fullname' => $patient->firstname ." ".$patient->lastname, 
                'contactNumber' => Settings::findConfigValue("CONTACT_PHONE_NUMBER"),
                'contactEmail' => Settings::findConfigValue("CONTACT_EMAIL"),
            ];
            $emails = [];
            if($patient->age > 17){
                if(isset($patient->email)){
                    array_push($emails,$patient->email);
                }
            }else{
                $emails = array_merge($emails, Patients::getEmailForRepresentatives($patient));
            }

            $this->dispatchEmailAppointmentWithTemplate($dataToSend,$emails,$model);
       
        };
        $sendEmail($model);
        $request->session()->flash('success', __("common.messageSuccessEmail"));
        return view("detail-appointment",[
            "model"=>$model
        ]);
        
    }

   

    /**
     * 
     */
    public function create(Request $request){
        try {
            $model = new Appointments();
            if(!($request->method() === "POST")){
                $doctors = User::getAllDoctors();
                $calendar       = $this->getCalendarAppointment();
                $patients       = Patients::all();
                $especialities  = Especiality::getEspecialities();
                return view("create-appointment",[
                    "appointment"=>$model,
                    "patients"=>$patients,
                    "especialities"=>$especialities,
                    "calendar"=>$calendar,
                    "doctors"=>$doctors
                ]);
            }

          
            $data = $model->createModelFromRequest($request->all());



            $newAppointmentDate  = Carbon::instance($data["date"]);
            $startRange = $newAppointmentDate->copy()->subMinutes(29);
            $endRange = $newAppointmentDate->copy()->addMinutes(29);


            $existingAppointments = Appointments::whereBetween('date', [$startRange, $endRange])
            ->where('users_id', $data["users_id"]) 
            ->get();


           
        if ($existingAppointments->isEmpty()) {
            // En lugar de guardar directamente, almacenamos en sesión
            if(isset($request->all()["appointment_tags"])){
                session(['pending_appointment' => $data, "appointment_tags" => $request->all()["appointment_tags"]]);
            }else{
                session(['pending_appointment' => $data]);
            }
            
            // Redirigir al formulario de pago con indicador de cita pendiente
            return redirect()->route('/admin/payment-for-appointment');
        }else{
            $dataForm = $request->all();
            $request->session()->flash('error', __("error-500.appointmentBusy"));
            return redirect()->back()->withInput($dataForm);
        }
        } catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }



    /**
     * 
     */
    public function createExternal(Request $request){
        try {
            
            $model = new Appointments();
            if(!($request->method() === "POST")){
                $doctors = User::getAllDoctors();
                $calendar       = $this->getCalendarAppointment();
                $patients       = Patients::all();
                $especialities  = Especiality::getEspecialities();
                return view("create-appointment-external",[
                    "appointment"=>$model,
                    "patients"=>$patients,
                    "especialities"=>$especialities,
                    "calendar"=>$calendar,
                    "doctors"=>$doctors
                ]);
            }

           
            $data = $model->createModelFromRequest($request->all());
            $patientIdentificationNumber = $request->all()["patientIdentificationNumber"];
            $patientFromExternal = Patients::where("identification","=",$patientIdentificationNumber)->first();

            if(!isset($patientFromExternal)){
                $request->session()->flash('error', __("error-500.patientExternalNoFound"));
                return redirect()->back();
            }


            $data["patients_id"] = $patientFromExternal->id;

            

            $newAppointmentDate  = Carbon::instance($data["date"]);
            $startRange = $newAppointmentDate->copy()->subMinutes(59);
            $endRange = $newAppointmentDate->copy()->addMinutes(59);


            $existingAppointments = Appointments::whereBetween('date', [$startRange, $endRange])
            ->where('users_id', $data["users_id"]) 
            ->get();





           
        if ($existingAppointments->isEmpty()) {
            $model = $model->create($data);

            $sendEmail = function($model){
                $patient = $model->patient()->first();
                $date = new DateTime($model->date->format('Y-m-d H:i:s'), new DateTimeZone(Settings::findConfigValue("TIME_ZONE")));
                $dateStr = $date->format('d-m-Y');
                $hour = $date->format('g:i A');
                $dataToSend = [
                    'hour' => $hour,
                    'date' => $dateStr,
                    'fullname' => $patient->firstname ." ".$patient->lastname, 
                    'contactNumber' => Settings::findConfigValue("CONTACT_PHONE_NUMBER"),
                    'contactEmail' => Settings::findConfigValue("CONTACT_EMAIL"),
                ];
                $emails = [];
                if($patient->age > 17){
                    if(isset($patient->email)){
                        array_push($emails,$patient->email);
                    }
                }else{
                    $emails = array_merge($emails, Patients::getEmailForRepresentatives($patient));
                }
    
                $this->dispatchEmailAppointmentWithTemplate($dataToSend,$emails,$model);
            };

            $sendEmail($model);
           
            $request->session()->flash('success', __("com-form-appointment.successExternal"));
            return redirect()->back();
        }else{
            $dataForm = $request->all();
            $request->session()->flash('error', __("error-500.appointmentBusy"));
            return redirect()->back()->withInput($dataForm);
        }
        } catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }

    

    /**
     * 
     */
    public function createFromApi(Request $request){
        $fields = $request->json()->all();
        try {
            //guardar en la base de datos
            DB::beginTransaction();
                $representative     = Representative::getStructureFromRequest($fields);
                $representative     = Representative::createOrGetRepresentative($representative);
                
                $patients = Patients::getStructureFromRequest($fields);
                $patients =  Patients::createOrGetPatient($patients);                
            
                $relationship = RelationShip::getStructureFromRequest($fields,[
                    "representativeId" => $representative->id,
                    "patientsId"=>$patients->id
                ]);
                $relationship = RelationShip::create($relationship);

                $appointments = Appointments::getStructureFromRequest($fields,["patientsId"=>$patients->id]);
                $appointments = Appointments::create($appointments);

            //enviar notification por email al doctor
            $sendNotification = $this->sendNotification($fields);

            //enviar correo por email al representante o al paciente
            if(isset($fields["mail"])){
                $dispatchEmailAppointment = $this->dispatchEmailAppointment($patients,$appointments,$representative->email);
                $state = ((count($sendNotification) == 0)&&(count($dispatchEmailAppointment)==0));
            }else{
                $state = (count($sendNotification) == 0);
            } 
            DB::commit();
            return Response::getResponseCreateAppointment($state,$appointments->code,200);
        } catch (\Throwable $th) {
            DB::rollback();
            return Response::getResponseCreateAppointment([false,strval($th)],NULL,500);
        }
    }

    /**
     * 
     */
    private function sendNotification($fields){
        $from       = Helper::MAIL_TO_SEND;
        $emails     = array_merge([Helper::MAIL_TO_SEND],Helper::OTHERS_MAIL_TO_SEND);
        $subject    = Helper::SUBJECT_DEFAULT_NOTIFICATION;
        return Helper::sendEmail($from,$emails,$subject,$fields,AppointmentNotificationMail::class);
    }

    /**
     * 
     */
    private function dispatchEmailAppointment($patient,$appointments,$representativeEmail){
        return Helper::sendEmail(
            Helper::MAIL_TO_SEND,
            [$representativeEmail],
            Helper::SUBJECT_DEFAULT_MAIL_TO_SEND,
            [
                "patient"=>$patient,
                "appointments"=>$appointments
            ],
            AppointmentMail::class); 
    }

    /**
     * 
     */
    private function dispatchEmailAppointmentWithTemplate($data,$emails,$appointmentModel){
        Helper::sendWhatsAppMessage($appointmentModel);
        return Helper::sendEmail(
            Helper::MAIL_TO_SEND,
            $emails,
            Helper::SUBJECT_DEFAULT_MAIL_TO_SEND,
            $data,
            AppointmentMailWithTemplate::class,
            $appointmentModel); 
    }

    /**
     * 
     */
    public function getToken(){
        $token = csrf_token();
        return Response::getResponseToken($token,200);
    }

    /**
     * 
     */
    public function view(Request $request){
        try{
            $data = $request->all();
            $isToday = (isset($data["today"]) && ($data["today"] === "1"));
            $isMyAppointments = (isset($data["myAppointments"]) && ($data["myAppointments"] === "1"));
            $isPerday = (isset($data["day"]));

            if($isToday)
                $calendar = $this->getCalendarDatePatients($isToday);
            else if ($isMyAppointments)
                $calendar = $this->getCalendarDatePatientsForDoctor($isMyAppointments);
            else if($isPerday)
                $calendar = $this->getCalendarDatePerDay($data["day"]);
            else
                $calendar = $this->getCalendarDatePatients(false);
            $user = User::class;
        return view("view-appointments", compact("calendar","user"));
        }catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }

    /**
     * 
     */
    private function getCalendarAppointment(){
       try{
        $events = [];
        $calendar = new Calendar();
        $calendar->addEvents($events)
        ->setOptions([
            'plugins' => [ 'window.interaction', 'window.momentPlugin', 'window.dayGridPlugin', 'window.timeGridPlugin', 'window.listPlugin' ],
            'locales' => 'window.allLocales',
            'locale' => 'es',
            'firstDay' => 0,
            'displayEventTime' => true,
            'selectable' => true,
            'initialView' => 'dayGridMonth',
            'headerToolbar' => [
                'left' => 'prev,next today',
                'center' => 'title',
                'right' => 'dayGridMonth,timeGridWeek,timeGridDay'
            ],
            'customButtons' => [
                'myCustomButton' => [
                    'text'=> 'custom!',
                    'click' => 'function() {
                        alert(\'clicked the custom button!\');
                    }'
                ]
            ],
            'dayCellClassNames' => 'function(info) { 
                return window.doctorScheduleDays && window.doctorScheduleDays.includes(info.date.getDay()) ? "doctor-available-day" : "doctor-unavailable-day";
            }',
            'dayMaxEventRows' => 2,
            'selectable' => 'function(info) { 
                return window.doctorScheduleDays && window.doctorScheduleDays.includes(info.date.getDay());
            }',
        ]);
        $calendar->setId('calendar-2');
        $calendar->setEs6();
        $calendar->setCallbacks([
            'select' => 'function(info) {

                if ($("#doctorId").val()) {
                    window.appointmentDate = info.start;
                    let day = $.fn.getDays()[info.start.getDay()];
                    // $("#dateAppointment").val(window.translations["create-appointment"][day] +" - "+ info.start.toLocaleDateString());
                    $.dateAppointment = info.start;
                    console.log(window.dateAppointment);
                   // loadAvailableHours(info.start);
                } else {
                    alert(window.translations["create-appointment"]["selectDoctorFirst"]);
                    calendar.unselect();
                }
            }',
            'eventClick' => 'function(info) {

                window.location.href="?search="+info.event.id;
            }',
            'dateClick' => 'function(info) {
            const today = new Date(); // Obtiene la fecha y hora actuales
            today.setHours(0, 0, 0, 0);
                if ($("#doctorId").val()) {
                    if(window.cellCalendar !== undefined){
                        window.cellCalendar.style.background = "";
                    }
                    if(info.date < today){
                        alert("No puedes seleccionar una fecha pasada");
                        calendar.unselect();
                    }else{
                        if(window.doctorScheduleDays && window.doctorScheduleDays.includes(info.date.getDay())) {
                            window.cellCalendar = info.dayEl;
                            window.cellCalendar.style.background = "rgba(54, 135, 255, 0.73)";
                            window.appointmentDate = info.date;
                            let day = $.fn.getDays()[info.date.getDay()];
                           // $("#dateAppointment").val(window.translations["create-appointment"][day] +" - "+ info.date.toLocaleDateString());
                            $.dateAppointment = info.date;
                            console.log(window.dateAppointment);
                            loadAvailableHours(info.date);
                        }else{
                            alert(window.translations["create-appointment"]["doctorNotAvailable"]);
                            calendar.unselect();
                        }
                    }
                } else {
                    alert(window.translations["create-appointment"]["selectDoctorFirst"]);
                }
            }'
        ]);
        return $calendar;
       }catch (Throwable $th) {
        throw new GlobalException($th->getMessage());
        }
    }


    /**
     * 
     */
    private function getCalendarDatePatientsForDoctor($isMyAppointments = false){
        try{
            $events = [];
            $userId = Auth::user()->id;
        
            if($isMyAppointments === true)
                $appointments = Appointments::where("active",'=', '1')
                                ->where("users_id", '=', $userId)->get();
                                //$appointments = Appointments::where("active",'=', '1')->get();

            foreach($appointments as $appointment){
                $patient = $appointment->patient()->first();
                $date = new \DateTime($appointment->date);
                $date = date("Y-m-d\T0800", strtotime($date->format("Y-m-d")));
                $event = \Calendar::event(
                    $patient->firstname . " " .$patient->lastname, //event title
                    true, //full day event?
                    $date, //start time (you can also use Carbon instead of DateTime)
                    $date, //end time (you can also use Carbon instead of DateTime)
                    $appointment->id //optionally, you can specify an event ID
                );
                array_push($events,$event);
            }
    
            $calendar = new Calendar();
            $calendar->addEvents($events)
            ->setOptions([
                'plugins' => [ 'window.interaction', 'window.momentPlugin', 'window.dayGridPlugin', 'window.timeGridPlugin', 'window.listPlugin' ],
                'locales' => 'window.allLocales',
                'locale' => 'es',
                'firstDay' => 0,
                'displayEventTime' => true,
                'selectable' => true,
                'initialView' => 'dayGridMonth',
                'headerToolbar' => [
                    'left' => 'prev,next today',
                    'center' => 'title',
                    'right' => 'dayGridMonth,timeGridWeek,timeGridDay'
                ],
                'customButtons' => [
                    'myCustomButton' => [
                        'text'=> 'custom!',
                        'click' => 'function() {
                            alert(\'clicked the custom button!\');
                        }'
                    ]
                ]
            ]);
            $calendar->setId('calendar-1');
            $calendar->setEs6();
            $calendar->setCallbacks([
                'select' => 'function(info) {
                    //alert(\'selected \' + info.startStr + \' to \' + info.endStr);
                }',
                'eventClick' => 'function(info) {
                    window.location.href="detail-appointment?id="+info.event.id;
                }',
                'dateClick' => 'function(info) {
                    window.location.href="detail-appointment?id="+info.dateStr;
                }'
            ]);
            return $calendar;
    
        }catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }

    /**
     * 
     */
    private function getCalendarDatePatients($today = false){
        try{
            $events = [];
        
            if($today === true)
                $appointments = Appointments::where("active",'=', '1')->whereDate("date",Carbon::today())->get();
            else
                $appointments = Appointments::where("active",'=', '1')->get();

            foreach($appointments as $appointment){
                $patient = $appointment->patient()->first();
                $date = new \DateTime($appointment->date);
                $date = date("Y-m-d\T0800", strtotime($date->format("Y-m-d")));
                $event = \Calendar::event(
                    $patient->firstname . " " .$patient->lastname, //event title
                    true, //full day event?
                    $date, //start time (you can also use Carbon instead of DateTime)
                    $date, //end time (you can also use Carbon instead of DateTime)
                    $appointment->id //optionally, you can specify an event ID
                );
                array_push($events,$event);
            }
    
            $calendar = new Calendar();
            $calendar->addEvents($events)
            ->setOptions([
                'plugins' => [ 'window.interaction', 'window.momentPlugin', 'window.dayGridPlugin', 'window.timeGridPlugin', 'window.listPlugin' ],
                'locales' => 'window.allLocales',
                'locale' => 'es',
                'firstDay' => 0,
                'displayEventTime' => true,
                'selectable' => true,
                'initialView' => 'dayGridMonth',
                'headerToolbar' => [
                    'left' => 'prev,next today',
                    'center' => 'title',
                    'right' => 'dayGridMonth,timeGridWeek,timeGridDay'
                ],
                'customButtons' => [
                    'myCustomButton' => [
                        'text'=> 'custom!',
                        'click' => 'function() {
                            alert(\'clicked the custom button!\');
                        }'
                    ]
                ]
            ]);
            $calendar->setId('calendar-1');
            $calendar->setEs6();
            $calendar->setCallbacks([
                'select' => 'function(info) {
                    //alert(\'selected \' + info.startStr + \' to \' + info.endStr);
                }',
                'eventClick' => 'function(info) {
                    window.location.href="detail-appointment?id="+info.event.id;
                }',
                'dateClick' => 'function(info) {
                     window.location.href="detail-appointment?id="+info.dateStr;
                }'
            ]);
            return $calendar;
    
        }catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }


    /**
     * 
     */
    private function getCalendarDatePerDay($day){
        try{
            $events = [];
        
            $appointments = Appointments::where("active",'=', '1')->whereDate("date",Carbon::parse($day))->get();
           //$appointments = Appointments::where("active",'=', '1')->get();
            foreach($appointments as $appointment){
                $patient = $appointment->patient()->first();
                $date = new \DateTime($appointment->date);
                $date = date("Y-m-d\T0800", strtotime($date->format("Y-m-d")));
                $event = \Calendar::event(
                    $patient->firstname . " " .$patient->lastname, //event title
                    true, //full day event?
                    $date, //start time (you can also use Carbon instead of DateTime)
                    $date, //end time (you can also use Carbon instead of DateTime)
                    $appointment->code //optionally, you can specify an event ID
                );
                array_push($events,$event);
            }
    
            $calendar = new Calendar();
            $calendar->addEvents($events)
            ->setOptions([
                'plugins' => [ 'window.interaction', 'window.momentPlugin', 'window.dayGridPlugin', 'window.timeGridPlugin', 'window.listPlugin' ],
                'locales' => 'window.allLocales',
                'locale' => 'es',
                'firstDay' => 0,
                'displayEventTime' => true,
                'selectable' => true,
                'initialView' => 'dayGridMonth',
                'headerToolbar' => [
                    'left' => 'prev,next today',
                    'center' => 'title',
                    'right' => 'dayGridMonth,timeGridWeek,timeGridDay'
                ],
                'customButtons' => [
                    'myCustomButton' => [
                        'text'=> 'custom!',
                        'click' => 'function() {
                            alert(\'clicked the custom button!\');
                        }'
                    ]
                ]
            ]);
            $calendar->setId('calendar-1');
            $calendar->setEs6();
            $calendar->setCallbacks([
                'select' => 'function(info) {
                    //alert(\'selected \' + info.startStr + \' to \' + info.endStr);
                }',
                'eventClick' => 'function(info) {
                    window.location.href="?search="+info.event.id;
                }',
                'dateClick' => 'function(info) {
                     window.location.href="?day="+info.dateStr;
                }'
            ]);
            return $calendar;
    
        }catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }


    public function viewCloseAppointments(Request $request){
       try{
            $appointments = Appointments::where("active",'=', '0')->get();
            return view("close-appointments",[
                    "model"=>$appointments
            ]);
        }catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }

    /**
     * Cierra una cita marcándola como finalizada
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function closeAppointment(Request $request){
        try{
            $response = [];
            if($request->ajax()){
                $data = $request->json()->all();
                $id = $data["id"];
                $model = Appointments::find($id);
                
                // Cambiar el estado a Finalizada (2)
                $model->status = 2;
                $model->active = 0;
                $model->closed_at = now();
                $model->closed_by = auth()->id();
                
                $save = $model->save();
                $response =  [
                    "error"=>(!$save),
                    "status"=>"success",
                    "opstatus"=>0,
                    "message"=>"done"
                ];
                return response()->json($response);
            }
        }catch (Throwable $th) {
            $response =  [
                "error"=>true,
                "status"=>"error",
                "opstatus"=>500,
                "message"=>$th->getMessage()
            ];
            return response()->json($response);
        }
    }

    /**
     * Export appointments to Excel
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function export(Request $request)
    {
        try {
            $data = $request->all();
            $params = [];
            
            if (isset($data["today"]) && $data["today"] === "1") {
                $params['today'] = true;
                $filename = 'citas_hoy_' . date('Y-m-d') . '.xlsx';
            } elseif (isset($data["myAppointments"]) && $data["myAppointments"] === "1") {
                $params['myAppointments'] = true;
                $params['userId'] = Auth::id();
                $filename = 'mis_citas_' . date('Y-m-d') . '.xlsx';
            } elseif (isset($data["day"])) {
                $params['day'] = $data["day"];
                $fecha = Carbon::parse($data["day"])->format('Y-m-d');
                $filename = 'citas_' . $fecha . '.xlsx';
            } else {
                $filename = 'todas_las_citas_' . date('Y-m-d') . '.xlsx';
            }
            
            return Excel::download(new AppointmentExport($params), $filename);
        } catch (Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }

    /**
     * Reagendar una cita existente
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function rescheduleAppointment(Request $request)
    {
        try {
            $validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
                'appointment_id' => 'required|exists:appointments,id',
                'new_date' => 'required|string',
                'users_id' => 'nullable|string|exists:users,id',
            ]);

            if ($validator->fails()) {
                dd("aqui");
                return redirect()->back()
                    ->withErrors($validator)
                    ->withInput();
            }


            $appointmentId = $request->input('appointment_id');
            $newDate = $request->input('new_date');
            $newDoctorId = $request->input('users_id');

            $appointment = Appointments::findOrFail($appointmentId);
            
            // Guardar valores anteriores para notificación
            $oldDate = Carbon::parse($appointment->date);
            $oldDoctorId = $appointment->users_id;
            
            // Procesar nueva fecha
            try {
               // Normaliza la parte del tiempo (asegura horas, minutos y segundos de dos dígitos)
                $dateTimeParts = explode(' ', $newDate, 2);
                if (count($dateTimeParts) === 2) {
                    $timeParts = explode(':', $dateTimeParts[1]);
                    
                    // Asegura 3 componentes (hora, minuto, segundo)
                    $timeParts = array_pad($timeParts, 3, '00');
                    
                    // Formatea cada componente a dos dígitos
                    $timeParts = array_map(function($part) {
                        return str_pad($part, 2, '0', STR_PAD_LEFT);
                    }, array_slice($timeParts, 0, 3));
                    
                    $normalizedTime = implode(':', $timeParts);
                    $normalizedDate = $dateTimeParts[0] . ' ' . $normalizedTime;
                } else {
                    $normalizedDate = $newDate . ' 00:00:00'; // Si no tiene tiempo, añade uno por defecto
                }

                $parsedDate = Carbon::createFromFormat('d/m/Y H:i:s', $normalizedDate);
            } catch (\Exception $e) {
                
            dd($newDate);
                return redirect()->back()
                    ->with('error', 'Formato de fecha incorrecto. Por favor, intente de nuevo.')
                    ->withInput();
            }
            
            // Si no se especifica nuevo doctor, mantener el mismo
            if (empty($newDoctorId)) {
                $newDoctorId = $oldDoctorId;
            }

            // Verificar que el doctor trabaje en ese día y horario
            if (!Appointments::isDoctorAvailable($newDoctorId, $parsedDate)) {
                return redirect()->back()
                    ->with('error', __("error-500.doctorNotAvailable") ?? 'El doctor no está disponible en el horario seleccionado.')
                    ->withInput();
            }
            
            // Verificar si ya tiene una cita en ese horario
            $newAppointmentDate = Carbon::parse($parsedDate);
            $startRange = $newAppointmentDate->copy()->subMinutes(29);
            $endRange = $newAppointmentDate->copy()->addMinutes(29);

            $existingAppointments = Appointments::whereBetween('date', [$startRange, $endRange])
                ->where('users_id', $newDoctorId)
                ->where('id', '!=', $appointmentId) // Excluir la cita actual
                ->where('active', 1)
                ->where('deleted', 0)
                ->get();

            if ($existingAppointments->isNotEmpty()) {
                return redirect()->back()
                    ->with('error', __("error-500.appointmentBusy"))
                    ->withInput();
            }
            
            // Actualizar cita
            $appointment->date = $parsedDate;
            $appointment->users_id = $newDoctorId;
            $appointment->save();
            
            // Enviar notificación al paciente
            $patient = $appointment->patient()->first();
            $dateStr = $parsedDate->format('d-m-Y');
            $hour = $parsedDate->format('g:i A');
            $newDoctor = User::find($newDoctorId);
            
            $dataToSend = [
                'hour' => $hour,
                'date' => $dateStr,
                'fullname' => $patient->firstname . " " . $patient->lastname,
                'contactNumber' => Settings::findConfigValue("CONTACT_PHONE_NUMBER"),
                'contactEmail' => Settings::findConfigValue("CONTACT_EMAIL"),
                'message' => 'Su cita ha sido reagendada.',
                'parentEspecialityName' => Especiality::find($appointment->especiality_id)->name ?? ''
            ];
            
            $emails = [];
            if ($patient->age > 17) {
                if (isset($patient->email)) {
                    array_push($emails, $patient->email);
                }
            } else {
                $emails = array_merge($emails, Patients::getEmailForRepresentatives($patient));
            }

            $this->dispatchEmailAppointmentWithTemplate($dataToSend, $emails, $appointment);
            
            return redirect()->route("/admin/detail-appointment", ["id" => $appointment->id])
                ->with('success', 'Cita reagendada exitosamente.');
        } catch (\Throwable $th) {
            throw new GlobalException($th->getMessage());
        }
    }

    /**
     * Verifica si un doctor está disponible en una fecha y hora específica
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function getDoctorAvailableDays(Request $request)
    {
        try {
            $doctorId = $request->query('doctor_id');
            $dateStr = $request->query('date');
            
            if (!$doctorId || !$dateStr) {
                return response()->json([
                    'available' => false,
                    'message' => 'Parámetros incompletos'
                ]);
            }
            
            try {
                // Obtener y limpiar la fecha
                // Imprimir la fecha recibida para depuración
                \Log::info('Fecha recibida: ' . $dateStr);
                
                // Enfoque manual para parsear la fecha
                try {
                    // Primero intentar con formatos estándar
                    $formats = [
                        'd/m/Y H:i:s',
                        'd/m/Y H:i:S',
                        'd/m/Y H:i'
                    ];
                    
                    $date = null;
                    foreach ($formats as $format) {
                        try {
                            $date = Carbon::createFromFormat($format, $dateStr);
                            \Log::info('Formato exitoso: ' . $format);
                            break;
                        } catch (\Exception $e) {
                            // Continuar con el siguiente formato
                        }
                    }
                    
                    // Si ningún formato estándar funciona, intentar arreglar el formato
                    if ($date === null) {
                        // Analizar la fecha manualmente
                        if (preg_match('/(\d{2})\/(\d{2})\/(\d{4})\s+(\d{2}):(\d{2}):?(\d?)/', $dateStr, $matches)) {
                            $day = $matches[1];
                            $month = $matches[2];
                            $year = $matches[3];
                            $hour = $matches[4];
                            $minute = $matches[5];
                            $second = !empty($matches[6]) ? $matches[6] : '00';
                            
                            // Si los segundos tienen solo un dígito, agregar un cero
                            if (strlen($second) === 1) {
                                $second = '0' . $second;
                            }
                            
                            // Reconstruir la fecha en formato estándar
                            $formattedDate = "{$day}/{$month}/{$year} {$hour}:{$minute}:{$second}";
                            \Log::info('Fecha reconstruida: ' . $formattedDate);
                            
                            $date = Carbon::createFromFormat('d/m/Y H:i:s', $formattedDate);
                        } else {
                            throw new \Exception('No se pudo analizar el formato de fecha');
                        }
                    }
                } catch (\Exception $e) {
                    \Log::error('Error al procesar la fecha: ' . $e->getMessage());
                    return response()->json([
                        'available' => false,
                        'message' => 'Formato de fecha incorrecto: ' . $e->getMessage()
                    ]);
                }
                
                // Si llegamos aquí, se ha parseado correctamente la fecha
                \Log::info('Fecha parseada: ' . $date->format('d/m/Y H:i:s'));
            } catch (\Exception $e) {
                return response()->json([
                    'available' => false,
                    'message' => 'Formato de fecha incorrecto'
                ]);
            }
            
            // Verificar disponibilidad del doctor en su horario
            \Log::info('Verificando disponibilidad para el doctor: ' . $doctorId);
            \Log::info('Fecha y hora a verificar: ' . $date->format('d/m/Y H:i:s'));
            
            $isAvailable = Appointments::isDoctorAvailable($doctorId, $date);
            
            \Log::info('Resultado de verificación de disponibilidad: ' . ($isAvailable ? 'Disponible' : 'No disponible'));
            
            if (!$isAvailable) {
                return response()->json([
                    'available' => false,
                    'message' => 'El doctor no tiene horario disponible para este día y hora'
                ]);
            }
            
            // Verificar si ya tiene una cita en ese horario
            $startRange = $date->copy()->subMinutes(29);
            $endRange = $date->copy()->addMinutes(29);

            $existingAppointments = Appointments::whereBetween('date', [$startRange, $endRange])
                ->where('users_id', $doctorId)
                ->where('active', 1)
                ->where('deleted', 0)
                ->get();

            if ($existingAppointments->isNotEmpty()) {
                return response()->json([
                    'available' => false,
                    'message' => 'El doctor ya tiene una cita programada en este horario'
                ]);
            }
            
            return response()->json([
                'available' => true,
                'message' => 'El doctor está disponible en esta fecha y hora'
            ]);
            
        } catch (\Throwable $th) {
            return response()->json([
                'available' => false,
                'message' => 'Error al verificar disponibilidad: ' . $th->getMessage()
            ]);
        }
    }

    /**
     * Muestra formulario para pago adicional
     */
    public function additionalPayment(Payments $payment)
    {
        // Validar que el pago existe
        if (!$payment) {
            abort(404);
        }

        // Obtener datos necesarios
        $currencies = Currencies::all();
        $paymentMethods = PaymentMethods::all();
        $doctors = User::getAllDoctors();
        $medicalServices = MedicalService::all();
        $appointment = $payment->appointment;
        $optionsEspeciality = Especiality::getEspecialities();
        
        // Calcular deuda pendiente considerando pagos hijos
        $totalServices = $payment->medicalServices->sum('cost');
        $totalPaid = $payment->amount + $payment->children->sum('amount');
        $remainingDebt = max(0, $totalServices - $totalPaid);

        return view('payment-for-appointment', [
            'appointmentData' => [
                'id' => $appointment->id,
                'patients_id' => $appointment->patients_id,
                'users_id' => $appointment->users_id,
                'date' => $appointment->date,
                'reason' => $appointment->reason,
                'especiality' => $appointment->especiality_id
            ],
            'currencies' => $currencies,
            'paymentMethods' => $paymentMethods,
            'doctors' => $doctors,
            'payment' => $payment,
            'patient' => $appointment->patient,
            'doctor' => $appointment->user,
            'medicalServices' => $medicalServices,
            'optionsEspeciality' => $optionsEspeciality,
            'isAdditionalPayment' => true,
            'parentPayment' => $payment,
            'parentCurrency' => $payment->currency,
            'isChildPayment' => true,
            'parentAddress' => $payment->address_payer,
            'remainingDebt' => $remainingDebt
        ]);
    }
    
    /**
     * Procesa un pago adicional (hijo)
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Payments  $parentPayment
     * @return \Illuminate\Http\RedirectResponse
     */
    public function processAdditionalPayment(Request $request, Payments $payment)
    {
        try {
            // Validar que el pago padre existe
            if (!$payment) {
                return back()->with('error', 'Pago padre no encontrado');
            }
            
            // Validar que el pago no sea ya un pago hijo
            if ($payment->parent_id) {
                return back()->with('error', 'No se pueden realizar pagos adicionales sobre otro pago adicional');
            }
            
            $id = Helper::createId();
            $amount = str_replace(',', '.', str_replace('.', '', $request->input('amount')));
            $paymentMethods = $request->input('paymentMethods');
            $reason = $request->input('reason');
            $address_payer = $request->input('address_payer');
            $doctor_id = $request->input('doctors');
            $currency_id = $request->input('currency');
            $payer = $request->input('payer');
            $appointment_id = $payment->appointment_id;
            $parent_id = $payment->id;
            $especiality_id = $payment->especiality_id;
            $is_electronic = false;
            $user_reference = null;
            $reference = null;
           
            // Si es pago electrónico, usar referencia proporcionada por el usuario
            if ($request->input('is_electronic') && $request->input('user_reference') !== null) {
                $is_electronic = true;
                $user_reference = $request->input('user_reference');
                $reference = $request->input('user_reference');
            } else {
                // Si no es electrónico, generar referencia automática
                $reference = substr(Helper::createReferenceForPayments($doctor_id,$amount), 0, 255);
            }


            // Crear nuevo pago hijo
            $childPayment = new Payments([
                "id" => $id,
                "users_id" => $doctor_id,
                "especiality_id" => $especiality_id,
                "payment_methods_id" => $paymentMethods,
                "currencies_id" => $currency_id,
                "amount" => $amount,
                "description" => $reason,
                "payer" => $payer,
                "address_payer" => $address_payer,
                "active" => true,
                "is_electronic" => $is_electronic,
                "user_reference" => $user_reference,
                "reference" => $reference,
                "appointment_id" => $appointment_id,
                "parent_id" => $parent_id
            ]);


            
            // Guardar pago hijo
            $childPayment->save();

            
            // Asociar servicios médicos del padre
            if ($payment->medicalServices->count() > 0) {
                $childPayment->medicalServices()->attach($payment->medicalServices->pluck('id'));
            }
            
            // Redirigir a la vista de detalle del pago
            return redirect()
                ->route('admin.payments.show', ['payment' => $childPayment->id])
                ->with('success', 'Pago adicional registrado correctamente');
                
        } catch (\Exception $e) {
            // En caso de error, redirigir con mensaje de error
            throw new \Exception($e->getMessage());
           /* return back()
                ->withInput()
                ->with('error', 'Error al procesar el pago adicional: ' . $e->getMessage());*/
        }
    }
    
    /**
     * Agrega servicios médicos a un pago existente
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Payments  $payment
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
     */
    public function addServices(Request $request, Payments $payment)
    {
        try {
            // Validar que el pago existe y no es un pago hijo
            if (!$payment) {
                $message = 'Pago no encontrado';
                return $request->ajax() 
                    ? response()->json(['error' => $message], 404)
                    : back()->with('error', $message);
            }
            
            if ($payment->parent_id) {
                $message = 'No se pueden agregar servicios a un pago adicional';
                return $request->ajax()
                    ? response()->json(['error' => $message], 422)
                    : back()->with('error', $message);
            }
            
            // Validar que se hayan seleccionado servicios
            $selectedServices = $request->input('services', []);
            
            if (empty($selectedServices)) {
                $message = 'Debe seleccionar al menos un servicio médico';
                return $request->ajax()
                    ? response()->json(['error' => $message], 422)
                    : back()->with('error', $message);
            }
            
            // Iniciar una transacción para asegurar la integridad de los datos
            DB::beginTransaction();
            
            try {
                // Obtener los servicios seleccionados
                $services = \App\Models\MedicalService::whereIn('id', $selectedServices)->get();

                foreach ($selectedServices as $serviceId) {
                    $medicalService = MedicalService::find($serviceId);
                    $medicalServiceAttributes = $medicalService->toArray();
                    $medicalServiceAttributes['id'] = md5(uniqid(rand(), true) . Helper::createId());
                    $medicalServiceSnapshot = MedicalServiceSnapshot::create($medicalServiceAttributes);
                    // Asociar los servicios al pago sin datos adicionales
                    $payment->medicalServices()->attach($medicalServiceSnapshot->id);
                }
                
                //$payment->medicalServices()->attach($selectedServices);
                
                // Calcular el total de los servicios agregados
                $totalAmount = $services->sum('cost');
                
                // Confirmar la transacción
                DB::commit();
                
                // Respuesta exitosa
                $response = [
                    'success' => true,
                    'message' => 'Servicios médicos agregados correctamente al pago',
                    'redirect' => route('admin.payments.show', ['payment' => $payment->id])
                ];
                
                return $request->ajax()
                    ? response()->json($response)
                    : redirect()->route('admin.payments.show', ['payment' => $payment->id])
                                ->with('success', $response['message']);
                
            } catch (\Exception $e) {
                // Revertir la transacción en caso de error
                DB::rollBack();
                throw $e;
            }
            
        } catch (\Exception $e) {
            \Log::error('Error al agregar servicios al pago: ' . $e->getMessage());
            
            $errorMessage = 'Error al procesar la solicitud: ' . $e->getMessage();
            
            return $request->ajax()
                ? response()->json(['error' => $errorMessage], 500)
                : back()->withInput()->with('error', $errorMessage);
        }
    }
}
