<?php

namespace App\Http\Controllers;

use Agence104\LiveKit\AccessToken;
use Agence104\LiveKit\AccessTokenOptions;
use Agence104\LiveKit\RoomCreateOptions;
use Agence104\LiveKit\RoomServiceClient;
use Agence104\LiveKit\VideoGrant;
use App\Classes\MyChatbot;
use App\Events\AppointmentBooked;
use App\Events\PatientRegistered;
use App\Events\PaymentProcessed;
use App\Models\Appointment;
use App\Models\Cart;
use App\Models\DoctorAppointment;
use App\Models\Item;
use App\Models\ItemHistory;
use App\Models\Lab;
use App\Models\LabKit;
use App\Models\LabkitOrderItem;
use App\Models\MedicalHistoryAnswer;
use App\Models\MedicationCategory;
use App\Models\Notification;
use App\Models\Patient;
use App\Models\PatientAnswer;
use App\Models\PatientNote;
use App\Models\PatientPlan;
use App\Models\PatientPrescription;
use App\Models\PatientRegActivity;
use App\Models\Payment;
use App\Models\Plan;
use App\Models\PlanV1;
use App\Models\ProductCategory;
use App\Models\ProfileAnswer;
use App\Models\ProfileCategory;
use App\Models\ProfileCategoryQuestion;
use App\Models\ProfileGroup;
use App\Models\ProfileQuestion;
use App\Models\ProfileSubQuestion;
use App\Models\Question;
use App\Models\QuestionBuilder;
use App\Models\QuestionGroup;
use App\Models\Queue;
use App\Models\Setting;
use App\Models\Subscription;
use App\Models\Telemedpro;
use App\Rules\LuhnValid;
use App\Rules\TestCardRule;
use Carbon\Carbon;
use Carbon\CarbonTimeZone;
use DateTime;
use DateTimeZone;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\File;
use PhpOffice\PhpSpreadsheet\Calculation\Category;
use Illuminate\Contracts\Routing\UrlGenerator;

class PatientController extends Controller
{
    protected $url;
    public function __construct(UrlGenerator $url)
    {
        $this->url = $url;
    }
    public function registerPatient(Request $request)
    {
        $validatedData = $request->validate([
            'first_name' => 'required|string|max:255',
            'last_name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:patients',
            'password' => 'required',
            // 'state' => 'required',
            'dob' => 'required|date_format:Y-m-d',
            // 'address' => 'required',
            // 'country' => 'required',
            'phone_no' => 'required'
        ]);


        $defaultPassword = $validatedData['password'];

        $patient = Patient::create([
            'first_name' => $validatedData['first_name'],
            'last_name' => $validatedData['last_name'],
            'phone_no' => $validatedData['phone_no'],
            'email' => $validatedData['email'],
            'password' => Hash::make($defaultPassword),
            // 'city' => $validatedData['city'],
            // 'state' => $validatedData['state'],
            'dob' => $validatedData['dob'],
            // 'zip_code' => $request->input('zip_code') ?? "",
            // 'shipping_address' => $request->input('shipping_address') ?? "",
            // 'shipping_city' => $request->input('shipping_city') ?? "",
            // 'shipping_state' => $request->input('shipping_state') ?? "",
            // 'shipping_country' => $request->input('shipping_country') ?? "",
            // 'shipping_zipcode' => $request->input('shipping_zipcode') ?? "",
            // 'address' => $validatedData['address'],
            // 'lat' => $request->get('lat'),
            // 'long' => $request->get('long'),
            // 'country' => $validatedData['country'],
            'gender' => $request->input('gender') ?? "",
            // 'marital_status' => $request->input('marital_status') ?? "",
            // 'height' => $request->input('height') ?? "",
            // 'weight' => $request->input('weight') ?? "",
        ]);

        $token = $patient->createToken('auth_token')->plainTextToken;

        if ($patient->dob) {
            $birthDate = new DateTime($patient->dob);
            $today = new DateTime(date('Y-m-d'));
            $age = $today->diff($birthDate)->y;
            $patient->age = $age;
        } else {
            $patient->age = 0;
        }
        PatientRegActivity::create([
            'patient_id' => $patient->id,
            'activity' => 'patient_registered'
        ]);
        $setting = Setting::find(1);
        event(new PatientRegistered($patient, $validatedData));
        return response()
            ->json([
                'data' => $patient,
                'access_token' => $token,
                'token_type' => 'Bearer',
                'password' => $defaultPassword
            ]);
    }
    //write for

    public function forgotPassword(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
        ]);

        $patient = Patient::where('email', $request->email)->first();

        if (!$patient) {
            return response()->json(['message' => 'Email does not exist'], 404);
        }

        $token = Str::random(60);

        $patient->update(['remember_token' => $token]);

        // Send reset link email
        Mail::send('emails.password_reset', ['token' => $token], function ($message) use ($request) {
            $message->to($request->email);
            $message->subject('Password Reset Request');
        });

        return response()->json(['message' => 'Password reset link sent']);
    }

    public function resetPassword(Request $request)
    {
        $request->validate([
            'token' => 'required',
            'password' => 'required|confirmed',
        ]);

        $patient = Patient::where('remember_token', $request->token)->first();

        if (!$patient) {
            return response()->json(['message' => 'Invalid token'], 400);
        }

        $patient->update([
            'password' => Hash::make($request->password),
            'remember_token' => null,
        ]);

        return response()->json(['message' => 'Password reset successful']);
    }
    public function updatePatient(Request $request)
    {
        $patient = Auth::guard('patient')->user();

        // Collect only the fields that are present in the request
        $dataToUpdate = array_filter($request->only([
            'first_name',
            'last_name',
            'email',
            'phone_no',
            'city',
            'state',
            'address',
            'zip_code',
            'country',
            'dob',
            'gender',
            'marital_status',
            'height',
            'weight'
        ]), function ($value) {
            return $value !== null;
        });

        // Update the patient with the collected data
        $patient->update($dataToUpdate);
        return response()->json([
            'data' => $patient,
            'message' => 'Patient updated successfully'
        ]);
    }
    public function editPatient($id, Request $request)
    {
        $patient = Patient::where('id', $id)->first();
        if (!empty($request->input('address')))
            $patient->address = $request->input('address');
        if (!empty($request->input('city')))
            $patient->city = $request->input('city');
        if (!empty($request->input('state')))
            $patient->state = $request->input('state');
        if (!empty($request->input('zip_code')))
            $patient->zip_code = $request->input('zip_code');
        if (!empty($request->input('country')))
            $patient->country = $request->input('country');
        if (!empty($request->input('dob')))
            $patient->dob = $request->input('dob');
        if (!empty($request->input('gender')))
            $patient->gender = $request->input('gender');
        if (!empty($request->input('marital_status')))
            $patient->marital_status = $request->input('marital_status');
        if (!empty($request->input('height')))
            $patient->height = $request->input('height');
        if (!empty($request->input('weight')))
            $patient->weight = $request->input('weight');
        $patient->save();



        $patient->save();

        return response()->json([
            'data' => $patient,
            'message' => 'Patient updated successfully'
        ]);
    }

    // PatientController
    public function loginPatient(Request $request)
    {
        $validatedData = $request->validate([
            'email' => 'required|email',
            'password' => 'required'
        ]);

        $patient = Patient::where('email', $validatedData['email'])->firstOrFail();
        if ($patient->dob) {
            $birthDate = new DateTime($patient->dob);
            $today = new DateTime(date('Y-m-d'));
            $age = $today->diff($birthDate)->y;
            $patient->age = $age;
        } else {
            $patient->age = 0;
        }


        if (!$patient || !Hash::check($validatedData['password'], $patient->password)) {
            return response([
                'message' => 'Invalid credentials'
            ], 401);
        }

        $token = $patient->createToken('auth_token')->plainTextToken;

        return response()->json([
            'data' => $patient,
            'access_token' => $token,
            'token_type' => 'Bearer',
        ]);
    }
    public function updatePassword(Request $request)
    {

        $request->validate([
            /*  'old_password' => 'required', */
            'new_password' => 'required|string|min:8',
        ]);

        $patient = Auth::guard('patient')->user();
        // Check if the old password is correct
        /* if (!Hash::check($request->old_password, $patient->password)) {
            return response([
                'message' => 'The provided old password is incorrect.'
            ], 400); // Use 400 for bad request
        } */

        // Update the password
        $patient->password = Hash::make($request->new_password);
        $patient->save();

        return response()->json([
            'message' => 'Password updated successfully.'
        ]);
    }

    // Inside your AppointmentController class:

    public function availableSlots($date)
    {
        // Ensure date is in a valid format
        $date = Carbon::parse($date);
        $originalDate = Carbon::parse($date);

        // Generate all possible 30-minute slots between 9 AM and 4 PM
        $slots = collect();
        $startTime = Carbon::parse($date)->subHours(24)->setTime(9, 0, 0);
        $endTime = Carbon::parse($date)->addHours(24)->setTime(16, 0, 0);
        while ($startTime < $endTime) {
            $slots->push($startTime->format('Y-m-d H:i:s'));
            $startTime->addMinutes(15);
        }

        $user = Auth::guard('patient')->user();
        // Filter out booked slots
        $bookedAppointments = Appointment::where("patient_id", $user->id)
            ->where('appointment_date', '>=', $date->format('Y-m-d'))
            ->where('appointment_date', '<', $date->addDay()->format('Y-m-d'))
            ->pluck('appointment_date');

        $availableSlots = $slots->diff($bookedAppointments);

        $formattedSlots = $availableSlots->map(function ($slot) {
            $start = Carbon::parse($slot);
            $startTime = $start->format('Y-m-d H:i:s');
            return $startTime;
        });

        // Additional checking if slot is booked
        $formattedSlots = $formattedSlots->filter(function ($slot) use ($originalDate) {
            $time = Carbon::parse($slot);
            return !Appointment::where('appointment_time', $time->format('H:i:s'))
                ->where('appointment_date', $originalDate->format('Y-m-d'))
                ->exists();
        });

        return response()->json([
            'available_slots' => $formattedSlots->toArray()
        ]);
    }


    public function bookAppointment(Request $request)
    {
        $validatedData = $request->validate([
            /* 'telemed_pros_id' => 'required|exists:telemed_pros,id', */
            'patient_id' => 'required|exists:patients,id',
            'appointment_time' => 'required|date_format:H:i:s',
            'appointment_date' => 'required|date_format:Y-m-d',
            'patient_name' => 'required',
            'patient_email' => 'required',
            'timezone' => 'required',
        ]);
        try {
            $tz = new DateTimeZone($validatedData['timezone']);
            $standardTz = $tz->getName();
        } catch (Exception $e) {
            return response()->json([
                'message' => $e->getMessage()
            ], 400);
        }
        try {
            $timezoneMap = [
                'EST' => 'America/New_York',
                'EDT' => 'America/New_York',
                'CST' => 'America/Chicago',
                'CDT' => 'America/Chicago',
                'MST' => 'America/Denver',
                'MDT' => 'America/Denver',
                'PST' => 'America/Los_Angeles',
                'PDT' => 'America/Los_Angeles',
                // Add more mappings as needed
            ];
            $timezone = $validatedData['timezone'];
            if (array_key_exists($timezone, $timezoneMap)) {
                $timezone = $timezoneMap[$timezone];
            }

            $appointmentDateTime = new DateTime(
                $validatedData['appointment_date'] . ' ' . $validatedData['appointment_time'],
                new DateTimeZone($timezone)
            );

            $appointmentDateTime->setTimezone(new DateTimeZone('UTC'));

            $validatedData['appointment_time'] = $appointmentDateTime->format('H:i:s');
            $validatedData['appointment_date'] = $appointmentDateTime->format('Y-m-d');
        } catch (Exception $e) {
            return response()->json([
                'message' => $e->getMessage()
            ], 400);
        }

        $availableTelemedPros = Telemedpro::select("telemed_pros.id", "telemed_pros.name")/* ->where('is_busy', false) */
            ->leftJoin('appointments', function ($join) use ($validatedData) {
                $join->on('telemed_pros.id', '=', 'appointments.telemed_pros_id')
                    ->where('appointments.appointment_time', '=', $validatedData['appointment_time'])
                    ->where('appointments.appointment_date', '=', $validatedData['appointment_date']);
            })
            ->whereNull('appointments.id')
            ->first();

        if (!$availableTelemedPros)
            return response()->json([
                'message' => 'Appointment time not available'
            ], 400);

        $existingAppointment = Appointment::where('telemed_pros_id', $availableTelemedPros->id)
            ->where('appointment_time', $validatedData['appointment_time'])
            ->where('appointment_date', $validatedData['appointment_date'])
            ->first();

        if ($existingAppointment) {
            return response()->json([
                'message' => 'Appointment time not available'
            ], 400);
        }
        $validatedData['telemed_pros_id'] = $availableTelemedPros->id;
        $validatedData['status'] = 'pending';

        // Create the appointment
        $appointment = Appointment::create($validatedData);
        //$appointment_booking_tokens = $this->bookAppointmentApi($appointment, $availableTelemedPros);
        $appointment_booking_tokens = "null";
        /* $appointment->agent_call_token = $appointment_booking_tokens['tokenAgent'];
        $appointment->patient_call_token = $appointment_booking_tokens['tokenPatient']; */
        $appointment->agent_call_token = "null";
        $appointment->patient_call_token = "null";
        $appointment->save();

        PatientRegActivity::create([
            'patient_id' => $validatedData['patient_id'],
            'activity' => 'patient_appointment_booked'
        ]);
        $patient = $appointment->patient;
        $datetimeUtc = $appointment->appointment_date . ' ' . $appointment->appointment_time;
        $dateTimeUtc = Carbon::createFromFormat('Y-m-d H:i:s', $datetimeUtc, 'UTC');
        $appointmentTimeZone = new CarbonTimeZone($appointment->timezone);
        $dateTimeInAppointmentTimeZone = $dateTimeUtc->setTimezone($appointmentTimeZone);
        $appointment->appointment_date = $appointmentDate = $dateTimeInAppointmentTimeZone->format('Y-m-d');
        $appointment->appointment_time = $appointmentTime = $dateTimeInAppointmentTimeZone->format('H:i:s');
        $setting = Setting::find(1);
        event(new AppointmentBooked($appointment));
        $cart = Cart::find($request->input("cart_id"));
        $cart->appointment_id = $appointment->id;
        $cart->save();
        return response()->json([
            'message' => 'Appointment booked successfully',
            'meeting_id' => $appointment->agent_call_token,
            'appointment' => $appointment,
            'appointment_time' => $validatedData['appointment_time'],
            'appointment_date' => $validatedData['appointment_date']
        ]);
    }

    public function appointmentDetail(Appointment $appointment)
    {
        $patient = Patient::find($appointment->patient_id);
        $telemedPro = Telemedpro::find($appointment->telemed_pros_id);
        $doctor_appointment = DoctorAppointment::select('doctor_appointments.*', 'doctors.name as name')->where('appointment_id', $appointment->id)
            ->leftjoin('doctors', 'doctors.id', '=', 'doctor_appointments.doctor_id')
            ->first();
        if (!$doctor_appointment)
            $doctor_appointment = [];
        else
            $doctor_appointment = $doctor_appointment->toArray();
        return response()->json([
            'patient' => $patient->toArray() ?? [],
            'telemedPro' => $telemedPro->toArray() ?? [],
            'doctor_appointment' => $doctor_appointment,
            'video_url' => "https://plugnmeet.codelfi.com/recordings/" . $appointment->video_token . ".mp4",
        ]);
    }
    public function bookAppointmentApi($appointment, $availableTelemedPros)
    {
        $roomName = 'appointment-' . $appointment->id . "-" . uniqid();
        $opts = (new RoomCreateOptions())
            ->setName($roomName)
            ->setEmptyTimeout(10)
            ->setMaxParticipants(5);
        $host = "https://plugnmeet.codelfi.com";
        $svc = new RoomServiceClient($host, config('app.LK_API_KEY'), config('app.LK_API_SECRET'));
        $room = $svc->createRoom($opts);

        $participantPatientName = "patient-" . uniqid() . $appointment->patient->first_name . " " . $appointment->patient->last_name;

        $tokenOptionsPatient = (new AccessTokenOptions())
            ->setIdentity($participantPatientName);
        $videoGrantPatient = (new VideoGrant())
            ->setRoomJoin()
            ->setRoomName($roomName);
        $tokenPatient = (new AccessToken(config('app.LK_API_KEY'), config('app.LK_API_SECRET')))
            ->init($tokenOptionsPatient)
            ->setGrant($videoGrantPatient)
            ->toJwt();

        $participantAgentName = "agent-" . uniqid() . $availableTelemedPros->name;
        $tokenOptionsAgent = (new AccessTokenOptions())
            ->setIdentity($participantAgentName);
        $videoGrantAgent = (new VideoGrant())
            ->setRoomJoin()
            ->setRoomName($roomName);
        $tokenAgent = (new AccessToken(config('app.LK_API_KEY'), config('app.LK_API_SECRET')))
            ->init($tokenOptionsAgent)
            ->setGrant($videoGrantAgent)
            ->toJwt();
        return [
            'tokenPatient' => $tokenPatient,
            'tokenAgent' => $tokenAgent,
        ];
    }
    public function addPatientToQueue($patientId)
    {

        // Try to get existing queue
        $queue = Queue::where('patient_id', $patientId)->first();

        // No existing queue
        if (!$queue) {

            // Create new queue entry
            $queue = new Queue;
            $queue->patient_id = $patientId;
            $queue->queue_number = Queue::max('queue_number') + 1;
            $queue->save();

            return response()->json([
                'message' => 'Added to queue',
                'queue_number' => $queue->queue_number
            ]);
        } else {

            if ($queue->queue_number == 0) {
                $appointment = Appointment::create([
                    'patient_id' => $patientId,
                    'appointment_date' => Carbon::now()->format('Y-m-d'),
                    'appointment_time' => Carbon::now()->format('H:i:s'),
                ]);
                return response()->json([
                    'message' => 'ok',
                    'meeting_id' => $appointment->meeting_id,
                    'queue_number' => 0
                ]);
            } else {

                return response()->json([
                    'message' => 'Waiting in queue',
                    'queue_number' => $queue->queue_number
                ]);
            }
        }
    }
    public function getAppointmentsByPatientId(int $patientId)
    {
        try {
            $appointments = Appointment::where('patient_id', $patientId)
                ->with('telemedPro') // Eager load the associated telemed pro
                /* ->orderBy('appointment_time', 'desc') */ // Optional: sort by appointment time
                ->get();

            return response()->json($appointments, 200);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Failed to retrieve appointments'], 500);
        }
    }
    public function getDoctorAppointmentsByPatientId(int $patientId)
    {
        try {
            $appointments = DoctorAppointment::select("patients.first_name", "patients.last_name", "doctor_appointments.*") // Eager load the associated telemed pro
                ->leftJoin("patients", "patients.id", "doctor_appointments.patient_id")
                ->where('patient_id', $patientId)
                /* ->orderBy('appointment_time', 'desc')  */ // Optional: sort by appointment time
                ->get();

            return response()->json($appointments, 200);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Failed to retrieve appointments'], 500);
        }
    }
    public function getLabcorpData(Request $request)
    {
        $url = 'https://www.labcorp.com/labs-and-appointments/results';

        $params = [
            'geo_address' => $request->input('address'),
            'address_single' => $request->input('address'),
            'city' => $request->input('city'),
            'state' => $request->input('state'),
            'zip' => $request->input('zip'),
            'service' => 'ROUTINE_PHLEBOTOMY',
            'radius' => 25,
            'gps' => false,
        ];

        $response = Http::get($url, $params);
        // Check if the request was successful (status code 200)
        if ($response->successful()) {
            // Extract JSON using regular expressions
            $pattern = '/<script type="application\/json" data-drupal-selector="drupal-settings-json">(\{.*?\})<\/script>/s';
            preg_match($pattern, $response->body(), $matches);

            // Check if JSON data was found
            if (isset($matches[1])) {
                $jsonString = $matches[1];
                $jsonString = json_decode($jsonString);

                $data = [
                    'status' => 'success',
                    'data' => $jsonString
                ];
            } else {
                // JSON data not found in the response
                $data = [
                    'status' => 'fail'
                ];
            }
        } else {
            $data = [
                'status' => 'fail'
            ];
        }
        return response()->json($data);
    }
    public function patientBookLabGet(Appointment $appointment)
    {
        $lab = Lab::where("appointment_id", $appointment->id)->first();
        return response()->json([
            'lab_name' => $lab->name,
            'lab_address' => $lab->address,
            'lab_city' => $lab->city,
            'lab_state' => $lab->state,
            'lab_distance' => $lab->distance,
            'lab_contact_no' => $lab->contact_no,
            'lab_lang' => $lab->lang,
            'lab_lat' => $lab->lat,
            'slot_date' => $lab->slot_date,
            'slot_time' => $lab->slot_time,
            'booking_time' => $lab->booking_time,
        ]);
    }
    public function switchButton(Patient $patient, $switch)
    {
        if ($switch == 1)
            $patient->recording_switch = $switch;
        else
            $patient->recording_switch = 0;
        $patient->save();

        return response()->json([
            'message' => 'Recording Switched: ' . $switch
        ]);
    }
    public function switchButtonGet(Patient $patient)
    {
        return response()->json([
            'recording_switch' => $patient->recording_switch,
        ]);
    }
    public function patientQuestions(Request $request)
    {
        if ($request->input("message") && $request->input("token") && $request->input("token") == "gM=L8oq6BvdUCOff0v-q-fbx4RA68n-4IWB=V65!ZCZLhF6!CxgKVhq7x") {
            $yourApiKey = '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';
            $nlp = new MyChatbot($yourApiKey);
            return response()->json(['question' => $request->input("message"), 'answer' => $nlp->ask($request->input("message"))['response']], 200);
        }
        return response()->json(['error' => 'Incorrect Request'], 200);
    }
    public function getMedicalHistoryQuestion(Patient $patient, Request $request)
    {
        $user = Auth::guard('patient')->user();
        $answers = MedicalHistoryAnswer::where('patient_id', $user->id)->get();

        return response()->json([
            'status' => 'Success',
            'answers' => $answers
        ], 200);
    }
    public function postMedicalHistoryQuestion(Patient $patient, Request $request)
    {
        $user = Auth::guard('patient')->user();

        foreach ($request->answers as $answer) {
            $existing = MedicalHistoryAnswer::where("patient_id", $user->id)->where('question_key', $answer['question_key'])->first();

            if ($existing) {
                $existing->answer = $answer['answer'];
                $existing->patient_id = $user->id;
                $existing->type = $answer['type'];
                $existing->save();
            } else {
                $newAnswer = new MedicalHistoryAnswer();
                $newAnswer->question_key = $answer['question_key'];
                $newAnswer->patient_id = $user->id;
                $newAnswer->answer = $answer['answer'];
                $newAnswer->type = $answer['type'];
                $newAnswer->save();
            }
        }

        PatientRegActivity::create([
            'patient_id' => $user->id,
            'activity' => 'patient_medical_question_entered'
        ]);

        return response()->json(['status' => 'Success'], 200);
    }

    public function storeOrderData(LabKit $labkit, Request $request)
    {
        $user = Auth::guard('patient')->user();
        $cart = new Cart();
        $cart->lab_kit_id = $labkit->id;
        $cart->first_name = $request->first_name;
        $cart->last_name = $request->last_name;
        /* $cart->appointment_id = $request->appointment_id; */
        $cart->email = $request->email;
        $cart->phone = $request->phone;
        $cart->status = "pending";
        $cart->prescription_status = "pending";



        $cart->date_of_birth = $request->date_of_birth ?? null;

        $cart->patient_id = $user->id;

        $cart->shipping_address1 = $request->shipping_address1;
        $cart->shipping_address2 = $request->shipping_address2;
        $cart->shipping_city = $request->shipping_city;
        $cart->shipping_state = $request->shipping_state;
        $cart->shipping_zipcode = $request->shipping_zipcode;
        $cart->shipping_country = $request->shipping_country;

        $cart->billing_address1 = $request->billing_address1;
        $cart->billing_address2 = $request->billing_address2;
        $cart->billing_city = $request->billing_city;
        $cart->billing_state = $request->billing_state;
        $cart->billing_zipcode = $request->billing_zipcode;
        $cart->billing_country = $request->billing_country;
        $cart->short_description = "Your order has been placed successfully";
        $cart->shipping_amount = $request->shipping_amount;
        $cart->total_amount = $request->total_amount;

        $cart->save();

        if ($request->has('items')) {
            foreach ($request->items as $itemData) {
                $item = new Item();
                $item->plans_id = $itemData['plans_id'];
                $item->quantity = $itemData['quantity'];


                $item->status = "pending";
                $item->labkit_delivery_status = "pending";
                $item->cart_id = $cart->id;
                $item->save();

                $itemHistory = new ItemHistory();
                $itemHistory->note = "Order was placed (Order ID: #" . $cart->id . ")";
                $itemHistory->short_description = "Your order has been placed successfully";
                $itemHistory->cart_id = $cart->id;
                $itemHistory->status = "pending";
                $itemHistory->item_id = $item->id;
                if (isset($itemData['subscription']) && $itemData['subscription'] == true && $itemData['onetime'] == false) {
                    $subscription = new Subscription();
                    $subscription->subscription_start_date = Carbon::now();
                    $subscription->subscription_renewal_date = Carbon::now()->addDays(30);
                    $subscription->subscription_status = "Active";
                    $subscription->cart_id = $cart->id;
                    /* $subscription->status = "active"; */

                    $subscription->item_id = $item->id;
                    $subscription->patient_id = $user->id;

                    $subscription->save();
                }

                $itemHistory->save();

                $plan = PlanV1::find($itemData['plans_id']);
                if ($plan->is_prescription_required == true)
                    $labkitOrderItem = LabkitOrderItem::create([
                        'cart_id' => $cart->id,
                        'item_id' =>  $item->id,
                        'lab_kit_id' => 1,
                        /* 'result' => $request['result'], */
                        'status' => "Ordered",
                    ]);
            }
        }
        return response()->json(['status' => 'Success', 'cart' => $cart], 200);
    }


    public function getSubscriptionList()
    {
        $user = Auth::guard('patient')->user();
        $subscriptions = Subscription::with(['cart', 'item.plansV1'])
            ->where("subscription.patient_id", $user->id)
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($subscription) {
                $plan = $subscription->item->plansV1 ?? 'N/A';
                return [
                    'order_number' => $subscription->cart_id,
                    'subscription_id' => $subscription->id,
                    'product_title' => $plan->title ?? 'N/A',
                    'product_price' => [
                        'amount' => $plan->price ?? 0,
                        'currency' => $plan->currency ?? 'USD'
                    ],
                    'subscription_start_date' => $subscription->subscription_start_date,
                    'status' => $subscription->subscription_status,

                    'subscription_renewal_date' => $subscription->subscription_renewal_date,
                ];
            });

        return response()->json([
            'status' => 'Success',
            'subscriptions' => $subscriptions
        ], 200);
    }
    public function cancelSubscription(Subscription $subscription, Request $request)
    {
        $subscription->subscription_renewal_date = null;
        $subscription->subscription_status = $request->input('status');
        $subscription->save();
        return response()->json([
            'status' => 'Success',
            'subscriptions' => "Subscription canceled!"
        ], 200);
    }
    public function getPatientAppointmentsWithCartsAndItems(Request $request)
    {
        $user = Auth::guard('patient')->user();

        $appointments = Appointment::join('carts', 'appointments.id', '=', 'carts.appointment_id')
            ->join('items', 'carts.id', '=', 'items.cart_id')
            ->join('plans_v1', 'items.plans_id', '=', 'plans_v1.id')
            ->where('appointments.patient_id', $user->id)
            ->select(
                'appointments.*',
                'carts.id as cart_id',
                'carts.first_name as cart_first_name',
                'carts.last_name as cart_last_name',
                'carts.email as cart_email',
                'carts.phone as cart_phone',
                'carts.status as cart_status',
                'items.id as item_id',
                'items.status as item_status',
                'items.labkit_delivery_status',
                'plans_v1.title as plan_title',
                'plans_v1.currency as plan_currency',
                'plans_v1.price as plan_price'
            )
            ->get();

        $groupedAppointments = $appointments->groupBy('id');

        $result = $groupedAppointments->map(function ($appointmentGroup) {
            $carts = $appointmentGroup->groupBy('cart_id')->map(function ($cartGroup) {
                $items = $cartGroup->map(function ($item) {
                    return [
                        'id' => $item->item_id,
                        'status' => $item->item_status,
                        'labkit_delivery_status' => $item->labkit_delivery_status,
                        'plan' => [
                            'title' => $item->plan_title,
                            'currency' => $item->plan_currency,
                            'price' => $item->plan_price
                        ]
                    ];
                });
                $firstCart = $cartGroup->first();
                return [
                    'id' => $firstCart->cart_id,
                    'first_name' => $firstCart->cart_first_name,
                    'last_name' => $firstCart->cart_last_name,
                    'email' => $firstCart->cart_email,
                    'phone' => $firstCart->cart_phone,
                    'status' => $firstCart->cart_status,
                    'items' => $items->values()
                ];
            });

            $firstAppointment = $appointmentGroup->first();
            return [
                'id' => $firstAppointment->id,
                'telemed_pros_id' => $firstAppointment->telemed_pros_id,
                'patient_id' => $firstAppointment->patient_id,
                'appointment_time' => $firstAppointment->appointment_time,
                'in_call' => $firstAppointment->in_call,
                'meeting_id' => $firstAppointment->meeting_id,
                'agent_call_token' => $firstAppointment->agent_call_token,
                'patient_call_token' => $firstAppointment->patient_call_token,
                'video_token' => $firstAppointment->video_token,
                'appointment_date' => $firstAppointment->appointment_date,
                'patient_email' => $firstAppointment->patient_email,
                'patient_name' => $firstAppointment->patient_name,
                'timezone' => $firstAppointment->timezone,
                'analytics' => $firstAppointment->analytics,
                'start_time' => $firstAppointment->start_time,
                'end_time' => $firstAppointment->end_time,
                'duration' => $firstAppointment->duration,
                'carts' => $carts->values()
            ];
        });

        return response()->json(['status' => 'Success', 'appointments' => $result], 200);
    }
    public function getOrderData(Cart $cart, Request $request)
    {
        $user = Auth::guard('patient')->user();
        $cart = Cart::where("id", $cart->id)->where("patient_id", $user->id)->firstOrFail();
        $items = Item::where("cart_id", $cart->id)->get();
        return response()->json(['status' => 'Success', 'cart' => $cart, 'items_activity' => $items], 200);
    }
    public function getLatestOrderData(Request $request)
    {
        $user = Auth::guard('patient')->user();
        $cart = Cart::where("patient_id", $user->id)->orderBy('id', 'DESC')->first();
        return response()->json(['status' => 'Success', 'cart' => $cart], 200);
    }
    public function getPatientLabKits()
    {
        $user = Auth::guard('patient')->user();

        $labKits = LabKit::join('carts', 'lab_kit.id', '=', 'carts.lab_kit_id')
            ->where('carts.patient_id', $user->id)
            ->select(
                'lab_kit.*',
                'carts.status',
                'carts.total_amount',
                'carts.created_at as order_date'
            )
            ->orderBy('carts.created_at', 'desc')
            ->get();

        return response()->json([
            'status' => 'Success',
            'labKits' => $labKits
        ], 200);
    }
    public function updateStatusOrderData(Cart $cart, Request $request)
    {
        $user = Auth::guard('patient')->user();
        $cart = Cart::where("id", $cart->id)->where("patient_id", $user->id)->firstOrFail();
        $cart->status = $request->input("status");

        $cart->save();

        return response()->json(['status' => 'Success', 'cart' => $cart], 200);
    }

    /* public function processPayment(Request $request)
    {
        $patient = Auth::guard('patient')->user();
        event(new PaymentProcessed($patient));
        return response()->json(['status' => 'Success'], 200);
    } */
    public function processPayment(Request $request)
    {
        // Validate the incoming request
        $patient = Auth::guard('patient')->user();
        $currentYear = date('Y');
        $validatedData = $request->validate([
            'card_number' => ['required', 'string', 'max:16', new LuhnValid(), new TestCardRule()],
            'cvv' => 'required|string|max:4',
            'expiration_year' => 'required|string|size:4',
            'expiration_month' => 'required|string|size:2',
            'order_id' => 'required|string|max:255',
        ]);

        $expirationDate = \Carbon\Carbon::createFromDate($validatedData['expiration_year'], $validatedData['expiration_month'], 1)->endOfMonth();
        if ($expirationDate->isPast()) {
            return response()->json(['status' => 'Error', 'message' => 'The card has already expired.'], 422);
        }

        // Create a new payment record
        $payment = Payment::create([
            'card_number' => $validatedData['card_number'],
            'cvv' => $validatedData['cvv'],
            'expiration_year' => $validatedData['expiration_year'],
            'expiration_month' => $validatedData['expiration_month'],
            'order_id' => $validatedData['order_id'],
        ]);

        // You might want to add actual payment processing logic here

        // Assuming you want to keep the PaymentProcessed event
        event(new PaymentProcessed($patient));

        return response()->json(['status' => 'Success', 'message' => 'Payment processed successfully'], 200);
    }
    public function getPatient(Patient $patient, Request $request)
    {
        if (isset($patient->profile_picture))
            $patient->profile_picture = $this->url->to("storage/profile_pictures/" . $patient->profile_picture);
        else
            $patient->profile_picture =  null;
        $plans = PlanV1::all();

        foreach ($plans as $plan) {
            $filePath = public_path("assets/product/{$plan->id}.webp");
            if (File::exists($filePath)) {
                $plan->image_url = url("/assets/product/{$plan->id}.webp");
            } else {
                $plan->image_url = null;
            }
        }

        return response()->json(['status' => 'Success', 'patient' => $patient], 200);
    }
    public function getAgentAppointment(Appointment $appointment)
    {
        try {
            $appointments = Appointment::select("patients.first_name", "patients.last_name", "telemed_pros.name as agent_name", "appointments.*") // Eager load the associated telemed pro
                ->leftJoin("telemed_pros", "telemed_pros.id", "appointments.telemed_pros_id")
                ->leftJoin("patients", "patients.id", "appointments.patient_id")
                ->where("appointments.id", $appointment->id)
                ->first();

            return response()->json($appointments, 200);
        } catch (\Exception $e) {

            return response()->json(['error' => 'Failed to retrieve appointments'], 500);
        }
    }
    public function getAgentLastAppointment(Patient $patient, Request $request)
    {
        try {
            $appointments = Appointment::select(
                "patients.first_name",
                "patients.last_name",
                "telemed_pros.name as agent_name",
                "appointments.*",
                "carts.shipping_address1",
                "carts.shipping_address2",
                "carts.id as order_id",
                "carts.shipping_city",
                "carts.shipping_state",
                "carts.shipping_zipcode",
                "carts.shipping_country"

            ) // Eager load the associated telemed pro
                ->leftJoin("telemed_pros", "telemed_pros.id", "appointments.telemed_pros_id")
                ->leftJoin("patients", "patients.id", "appointments.patient_id")
                ->leftJoin("carts", "carts.appointment_id", "appointments.id")
                ->where("appointments.patient_id", $patient->id)
                ->orderBy('appointments.created_at', 'desc')
                ->first();

            $upcoming_appointments = Appointment::select(
                "patients.first_name",
                "patients.last_name",
                "telemed_pros.name as agent_name",
                "appointments.*",
                "carts.shipping_address1",
                "carts.shipping_address2",
                "carts.id as order_id",
                "carts.shipping_city",
                "carts.shipping_state",
                "carts.shipping_zipcode",
                "carts.shipping_country",
                "appointments.id as order_appointment_id"

            ) // Eager load the associated telemed pro
                ->leftJoin("telemed_pros", "telemed_pros.id", "appointments.telemed_pros_id")
                ->leftJoin("patients", "patients.id", "appointments.patient_id")
                ->leftJoin("carts", "carts.appointment_id", "appointments.id")
                //->where('appointments.appointment_date', '<', $appointments->appointment_date)
                ->where("appointments.patient_id", $patient->id)
                ->where("appointments.status", 'pending')
                ->whereNull("appointments.start_time")

                ->orderBy('appointments.created_at', 'desc')
                ->get();

            if (!$appointments)
                return response()->json(['error' => 'No Record found.'], 500);

            $timezone = config('app.timezone');
            if ($appointments->timezone) {

                $tz = new DateTimeZone($appointments->timezone);

                $standardTz = $tz->getName();
                $appointmentDateTime = $appointmentCurrent = Carbon::parse($appointments->appointment_date . ' ' . $appointments->appointment_time)->shiftTimezone($standardTz);
                //$appointmentDateTime =  $appointmentDateTime->shiftTimezone($timezone);

                $appointmentCurrent = Carbon::now($timezone);

                $diff = $appointmentDateTime->diff($appointmentCurrent);

                if ($diff->invert == 0) {
                    // Appointment is in future, increment count
                    $diff = $diff->format('0 days 0 hours 0 minutes 0 seconds');
                } else

                    $diff = $diff->format('%a days %h hours %i minutes %s seconds');
            } else {
                $diff = "";
            }
            $filePath = public_path("assets/profiles/{$patient->id}.png");

            if ($patient->profile_picture)
                $patient->profile_picture = $this->url->to("storage/profile_pictures", $patient->profile_picture);
            else
                $patient->profile_picture = null;

            if (File::exists($filePath)) {
                $patient->url = "/assets/profiles/{$patient->id}.png";
            } else {
                $patient->url = null;
            }
            foreach ($upcoming_appointments as $upcoming_appointment) {

                if ($upcoming_appointment->timezone) {

                    $tz = new DateTimeZone($upcoming_appointment->timezone);

                    $standardTz = $tz->getName();
                    $appointmentDateTime = $appointmentCurrent = Carbon::parse($upcoming_appointment->appointment_date . ' ' . $upcoming_appointment->appointment_time)->shiftTimezone($standardTz);
                    //$appointmentDateTime =  $appointmentDateTime->shiftTimezone($timezone);

                    $appointmentCurrent = Carbon::now($timezone);

                    $diff = $appointmentDateTime->diff($appointmentCurrent);

                    if ($diff->invert == 0) {
                        // Appointment is in future, increment count
                        $diff = $diff->format('0 days 0 hours 0 minutes 0 seconds');
                    } else

                        $diff = $diff->format('%a days %h hours %i minutes %s seconds');
                } else {
                    $diff = "";
                }

                $upcoming_appointment->items_data = $this->getOrderItems($upcoming_appointment->order_id);
                $upcoming_appointment->time_diff = $diff;
            }

            return response()->json(['upcoming_appointments' => $upcoming_appointments, 'appointment' => $appointments, 'time_diff' => $diff, 'patient' => $patient, "items_data" => $this->getOrderItems($appointments->order_id)], 200);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Failed to retrieve appointments'], 500);
        }
    }
    public function getOrderItems($id)
    {
        $items = Item::leftJoin('plans_v1', 'items.plans_id', 'plans_v1.id')
            ->where('cart_id', $id)
            ->get();
        $totalPrice = 0;
        $totalShippingCost = 0;
        $total_products = 0;
        foreach ($items as $item) {

            $totalShippingCost += $item->shipping_cost;
            $item->total_price = $item->quantity * $item->price;
            $totalPrice += $item->total_price;
            $total_products += $item->quantity;
            $item->image_url = $this->url->to("product/" . $item->image_url);
        }

        return [
            "items_list" => $items,
            'total_amount' => $totalPrice,
            'total_shipping_cost' => $totalShippingCost,
            'total_products' => $total_products,
            'total' => $totalPrice + $totalShippingCost
        ];
    }
    public function updateMeetingAnalysis(Appointment $appointment, Request $request)
    {
        $appointment->analytics = $request->input("data");
        $appointment->save();
        return response()->json(['status' => 'success'], 200);
    }
    public function aiFlagCheck(Appointment $appointment)
    {
        $telemedPro = Telemedpro::find($appointment->telemed_pros_id);
        return response()->json(['status' => $telemedPro->ai_switch], 200);
    }
    public function savePlan(Patient $patient, Request $request)
    {

        $plan = PlanV1::where("id", $request->input("plan_id"))->first();
        $plan = PatientPlan::create([
            "plan_id" => $plan->id,
            "patient_id" => $patient->id,

        ]);
        return response()->json($plan, 200);
    }

    public function savePatientPlan(PlanV1 $plan, Request $request)
    {
        $patient = Auth::guard('patient')->user();
        $plan = PatientPlan::create([
            "plan_id" => $plan->id,
            "patient_id" => $patient->id,

        ]);

        return response()->json($plan, 200);
    }
    public function getPlanById(Plan $plan)
    {
        return response()->json($plan, 200);
    }
    public function getPlanByPatientId(Patient $patient)
    {

        $plans = PatientPlan::join('plans_v1', 'patient_plan.plan_id', '=', 'plans_v1.id')
            ->leftJoin('medication_categories', 'plans_v1.medication_category_id', '=', 'medication_categories.id')
            ->where('patient_plan.patient_id', $patient->id)
            ->select('plans_v1.*', 'medication_categories.category_name')
            ->orderBy('plans_v1.created_at', 'desc')
            ->get();

        return response()->json($plans, 200);
    }
    public function questionsAnswers($patient_id)
    {
        $questionsData = [];
        $answers = [];
        $groups = QuestionGroup::all();
        foreach ($groups as $group) {
            $questions = Question::where('group_id', $group->id)->get();
            foreach ($questions as $question) {

                $answer = PatientAnswer::where('question_id', $question->id)->where('patient_id', $patient_id)->first();
                if (isset($answer->answer))
                    $question->answer = $answer->answer;
                else
                    $question->answer = null;
            }
            $questionsData[$group->title] = $questions;
        }
        return response()->json(
            $questionsData
        );
    }
    public function uploadProfilePicture(Request $request)
    {
        $patient = Auth::guard('patient')->user();
        $patientId =  $patient->id;
        $request->validate([
            'profile_picture' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048' // Validation rules
        ]);

        $patient = Patient::findOrFail($patientId);

        if ($request->hasFile('profile_picture')) {
            $filenameWithExt = $request->file('profile_picture')->getClientOriginalName();
            $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
            $extension = $request->file('profile_picture')->getClientOriginalExtension();
            $fileNameToStore = $filename . '_' . time() . '.' . $extension;

            $path = $request->file('profile_picture')->storeAs('storage/profile_pictures', $fileNameToStore);

            $patient->profile_picture = $path;
            $patient->save();

            return redirect()->back()->with('success', 'Profile picture uploaded!');
        }

        return redirect()->back()->with('error', 'Error uploading profile picture.');
    }
    public function createProfileCategories(Request $request)
    {
        // Basic validation
        $request->validate([
            'name' => 'required|string',
            'status' => 'required|string',
            'icon' => 'nullable|string'
        ]);

        // Create the profile category
        $profileCategory = ProfileCategory::create($request->all());

        return response()->json([
            'message' => 'Profile Category created successfully',
            'data' => $profileCategory
        ], 201);
    }

    public function profileCategories($id)
    {
        $profileCategory = ProfileCategory::findOrFail($id);

        return response()->json([
            'data' => $profileCategory
        ], 200);
    }
    public function getProfileCategories()
    {
        $user = Auth::user();
        /* $getProfileCategories = ProfileCategory::get();
        return response()->json([
            'data' => $getProfileCategories
        ], 200); */
        // Get all profile categories
        $getProfileCategories = ProfileCategory::get();

        // Initialize an array to store category IDs and their corresponding question counts
        $categoryCounts = [];

        // Iterate through each profile category
        foreach ($getProfileCategories as $category) {
            // Calculate the count of questions associated with the category
            $questionCount = QuestionBuilder::where('customer_id', $user->id)->where('profile_category_id', $category->id)->count();
            $category->question_count = $questionCount;
        }

        // Return the profile categories with the added question counts
        return response()->json([
            'data' => $getProfileCategories
        ], 200);
    }

    /* public function createProfileQuestion($category_id, Request $request)
    {
        // Validation (adjust as needed)
        $request->validate([
            'category_id' => 'required|integer|exists:profile_categories,id',
            'group_name' => 'required|string',
            'group_desc' => 'required|string',
            'group_status' => 'required|string',
        ]);

        $profileGroup = ProfileGroup::create($request->all());

        return response()->json([
            'message' => 'Profile Group created',
            'data' => $profileGroup
        ], 201);
    } */

    /* public function getOneProfileGroup($id)
    {
        $profileGroup = ProfileGroup::with('category')->findOrFail($id);
        return response()->json([
            'data' => $profileGroup
        ], 200);
    } */

    public function getProfileQuestion($category_id)
    {
        $ProfileCategoryIds = ProfileCategoryQuestion::select("question_id")->where("category_id", $category_id)->get()->toArray();
        $profileQuestions = ProfileQuestion::where("id", $ProfileCategoryIds)->get();
        $profileQuestions = ProfileQuestion::join('profile_category_question', 'profile_questions.id', '=', 'profile_category_question.question_id')
            ->where('profile_category_question.category_id', $category_id)
            ->select('profile_questions.*', 'profile_category_question.category_id', 'profile_category_question.id as profile_category_question_id')
            ->get();
        foreach ($profileQuestions as $profileQuestion) {
            $profileQuestion->sub_questions = ProfileSubQuestion::where("category_id", $category_id)
                ->where("question_id", $profileQuestion->id)->with('subQuestions')->get();
        }
        return response()->json([
            'data' => $profileQuestions
        ], 200);
    }

    public function getProfileSubQuestion($category_id, $question_id)
    {
        $profileQuestions = ProfileSubQuestion::where("category_id", $category_id)
            ->where("question_id", $question_id)->with('subQuestions')->get();
        return response()->json([
            'data' => $profileQuestions
        ], 200);
    }

    public function getProfileSubSubQuestion($category_id, $question_id, $sub_question_id)
    {
        $profileQuestions = ProfileSubQuestion::where("category_id", $category_id)
            ->where("question_id", $question_id)
            ->where("parent_sub_question_id", $sub_question_id)
            ->get();
        return response()->json([
            'data' => $profileQuestions
        ], 200);
    }
    /* public function getProfileCategories()
    {
        $profileCategory = ProfileCategory::get();

        return response()->json([
            'data' => $profileCategory
        ], 200);
    }

    public function getGroupByCategory($category_id)
    {
        $getGroupByCategory = ProfileGroup::where('category_id', $category_id)->get();
        return response()->json([
            'data' => $getGroupByCategory
        ], 200);
    }

    public function getQuestionByGroup($group_id)
    {
        $getQuestionByGroup = ProfileQuestion::where('group_id', $group_id)->get();
        return response()->json([
            'data' => $getQuestionByGroup
        ], 200);
    } */
    public function createProfileQuestion(Request $request)
    {
        // Validation (adjust as needed)
        $request->validate([
            'answer' => 'required|string',
        ]);
        $patient = Auth::guard('patient')->user();

        $profileGroup = ProfileAnswer::create([
            'answer' => $request->input('answer'),
            'question_category_id' => $request->input('question_category_id'),
            'sub_question_id' => $request->input('sub_question_id'),
            'patient_id' => $patient->id,
        ]);

        return response()->json([
            'message' => 'Profile Answer created',
            'data' => $profileGroup
        ], 200);
    }
    public function questionBuilderStore($category, Request $request)
    {
        $data = $request->all();

        $questionBuilderData = [];
        $category = ProfileCategory::where("category_link", $category)->first();
        if (!$category)
            return response()->json([
                'message' => 'Invalid Category Link',
                'data' => ''
            ], 200);

        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $value = serialize($value);
            }
            if (!empty($value)) {
                $questionBuilderData[] = [
                    'key' => $key,
                    'value' => $value,
                    'profile_category_id' => $category->id,
                    'customer_id' => Auth::guard('patient')->user()->id
                ];
            }
        }
        // dd($questionBuilderData);
        $questionBuilder = QuestionBuilder::insert($questionBuilderData);

        $questionBuilder = QuestionBuilder::select('key', 'value')->get();

        // Convert the data to a key-value JSON format
        $jsonData = $questionBuilder->mapWithKeys(function ($item) {
            return [$item->key => $item->value];
        });
        // Store data+
        return response()->json([
            'message' => 'Data Inserted',
            'data' => $jsonData
        ], 200);
    }
    public function getQuestionBuilderStore(Request $request)
    {
        $user = $request->user();
        $questionBuilder = QuestionBuilder::select('key', 'value')->where("customer_id", $user->id)->get();
        $jsonData = $questionBuilder->mapWithKeys(function ($item) {
            // dd($item->value, );
            $value = '';
            if ($this->isSerialized($item->value)) {
                $value = unserialize($item->value);
            } else {
                $value = $item->value;
            }
            return [$item->key => $value];
        });
        // Store data
        return response()->json([
            'message' => 'Data Sent',
            'data' => $jsonData
        ], 200);
    }
    protected function isSerialized($str)
    {
        if (!is_string($str)) {
            return false;
        }
        $data = @unserialize($str);
        if ($data !== false || $str === 'b:0;') {
            // The second condition checks for a serialized boolean false
            return true;
        } else {
            return false;
        }
    }
    public function getPatientPrescriptions()
    {
        $patientPrescriptions = PatientPrescription::with('prescription')
            ->where('patient_id', Auth::guard('patient')->user()->id)
            ->get();
        $prescriptionData = [];

        foreach ($patientPrescriptions as $prescription) {
            $prescriptionData[] = [
                'patient' => $prescription->patient,
                'prescription' => $prescription->prescription,
                'direction_one' => $prescription->direction_one,
                'direction_two' => $prescription->direction_two,
                'dont_substitute' => $prescription->dont_substitute,
                'comments' => $prescription->comments,
                'appointment_id' => $prescription->appointment_id,
                'appointment' => $prescription->appointment
            ];
        }

        if (!$patientPrescriptions->isEmpty()) {
            return response()->json($prescriptionData);
        } else {
            return response()->json(['message' => 'Prescription not found'], 404);
        }
    }
    public function sessionHistory(Request $request)
    {
        $user = Auth::guard('patient')->user();

        // Assuming user can be either telemedPro or patient
        $history = Appointment::select(
            'appointments.*',
            'appointments.patient_id',
            'patients.first_name as patient_name',
            'carts.id as order_id',
            'carts.shipping_amount',
            'carts.total_amount'
        )
            ->leftJoin('patients', 'appointments.patient_id', '=', 'patients.id')
            ->leftJoin('carts', 'carts.appointment_id', '=', 'appointments.id')
            ->where(function ($query) use ($user) {
                $query->where('appointments.patient_id', $user->id);
            })->whereNotNull("end_time")
            ->orderBy('appointments.appointment_date', 'desc');
        if ($request->input('appointment_date') != "all") {
            $date = $request->input('appointment_date');
            $originalDate = Carbon::parse($date);
            $history->where('appointment_date', '>=', $originalDate->format('Y-m-d'));
        }
        $history = $history->get();

        return response()->json(['history' => $history]);
    }
    public function getNotePatient(Appointment $appointment, Request $request)
    {
        $user = Auth::guard('patient')->user();
        $patientNotes = PatientNote::where("patient_id", $user->id)
            ->where("appointment_id", $appointment->id)
            ->with('appointment')
            ->get();

        $data = $patientNotes->map(function ($patientNote) {
            return [
                'id' => $patientNote->id,
                'note' => $patientNote->note,
                'note_type' => $patientNote->note_type,
                'created_at' => $patientNote->created_at,
                'patient_id' => $patientNote->patient_id,
                'appointment' => $patientNote->appointment,
                'telemedPro' => $patientNote->telemedPro,
                'telemedPro' => $patientNote->appointment?->telemedPro
            ];
        });

        return response()->json([
            'message' => 'Patient notes retrieved',
            'data' => $data
        ], 200);
    }
    public function getPatientPrescription($appointment_id)
    {
        $user = Auth::guard('patient')->user();
        $patientPrescription = PatientPrescription::with('prescription')
            ->where('patient_id', $user->id)
            ->where('appointment_id', $appointment_id)
            ->get();

        $prescriptionData = [];

        foreach ($patientPrescription as $prescription) {
            $prescriptionData[] = [
                'patient' => $prescription->patient,
                'created_at' => $prescription->created_at,
                'updated_at' => $prescription->updated_at,
                'prescription' => $prescription->prescription,
                'direction_one' => $prescription->direction_one,
                'direction_two' => $prescription->direction_two,
                'dont_substitute' => $prescription->dont_substitute,
                'comments' => $prescription->comments,
                'appointment_id' => $prescription->appointment_id,
                'appointment' => $prescription->appointment,
                'telemedPro' => $prescription->appointment->telemedPro,
                "status" => $prescription->status
            ];
        }

        if (!$patientPrescription->isEmpty()) {
            return response()->json($prescriptionData);
        } else {
            return response()->json(['message' => 'Prescription not found'], 404);
        }
    }
    public function updatePrescriptionStatus(PatientPrescription $prescription, Request $request)
    {
        $user = Auth::guard('patient')->user();
        $cart = PatientPrescription::where("id", $prescription->id)->where("patient_id", $user->id)->firstOrFail();
        $cart->status = $request->input("status");
        $cart->save();

        return response()->json(['status' => 'Success', 'cart' => $cart], 200);
    }
    public function checkEmail(Request $request)
    {
        $patient = Patient::where("email", $request->input("email"))->first();
        if ($patient)
            return response()->json(['status' => 'Success', 'email' => "Exist"], 200);
        return response()->json(['status' => 'Success', 'email' => "Not Exist"], 200);
    }

    public function getAppointmentDetail(Appointment $appointment)
    {
        return response()->json(['appointment' => $appointment, 'telemedPro' => $appointment->telemedPro], 200);
    }
    public function getPlans(Request $request)
    {
        $plans = PlanV1::select(
            'plans_v1.*', // Select all columns from plans_v1
            'medication_categories.category_name as category_name'
        )
            ->leftJoin('medication_categories', 'plans_v1.medication_category_id', '=', 'medication_categories.id')
            ->get();

        return response()->json($plans);
    }


    public function planProductUpdate(Request $request)
    {

        $product_id = $request->input('product_id');
        $product_name = $request->input('product_name');
        $product_slug = $request->input('product_slug');
        $product_price = $request->input('product_price');
        $product_category = $request->input('product_category');
        $product_image = $request->input('product_image');

        self::product_category($product_category,$product_id);
        // Check if product exists
        $plan = PlanV1::find($product_id);

        if ($plan) {
            $plan->title = $product_name;
            $plan->currency = "$";
            $plan->list_one_title = $product_name;
            $plan->list_two_title = $product_name;
            $plan->list_sub_title = $product_name;
            $plan->slug = $product_slug;
            $plan->price = $product_price;
            $plan->image_url = $product_image;
            $plan->save();

            return response()->json(['message' => 'Product updated successfully', 'data' => $plan]);
        } else {
            // Create new product
            $plan = new PlanV1();
            $plan->id = $product_id;
            $plan->currency = "$";
            $plan->list_one_title = $product_name;
            $plan->list_two_title = $product_name;
            $plan->list_sub_title = $product_name;
            $plan->image_url = $product_image;
            $plan->title = $product_name;
            $plan->slug = $product_slug;
            $plan->price = $product_price;
            $plan->save();

            return response()->json(['message' => 'Product created successfully', 'data' => $plan]);
        }
    }
    public function planProductUpdateMultiple(Request $request)
    {
        $products = $request->input('products');

        foreach ($products as $productData) {
            $product_id = $productData['product_id'];
            $product_name = $productData['product_name'];
            $product_slug = $productData['product_slug'];
            $product_price = $productData['product_price'];
            $product_category = $productData['product_category'];
            $product_image = $productData['product_image'];

            self::product_category($product_category,$product_id);

            $plan = PlanV1::find($product_id);

            if ($plan) {
                // Update existing product
                $plan->title = $product_name;
                $plan->currency = "$";
                $plan->list_one_title = $product_name;
                $plan->list_two_title = $product_name;
                $plan->list_sub_title = $product_name;
                $plan->image_url = $product_image;
                $plan->slug = $product_slug;
                $plan->price = $product_price;
                $plan->save();
            } else {
                // Create new product
                $plan = new PlanV1();
                $plan->id = $product_id;
                $plan->currency = "$";
                $plan->list_one_title = $product_name;
                $plan->list_two_title = $product_name;
                $plan->list_sub_title = $product_name;
                $plan->image_url = $product_image;
                $plan->title = $product_name;
                $plan->slug = $product_slug;
                $plan->price = $product_price;
                $plan->save();
            }
        }
        return response()->json(['message' => 'Products updated successfully']);
    }
    private function product_category($product_category,$product_id)
    {
        $productCategory = ProductCategory::where('product_id',$product_id);
        if($productCategory)
        {
            $productCategory->delete();
        }
        $category_id = $product_category['id'];
        $category_name = $product_category['name'];
        foreach($category_id as $key => $cat_id)
        {
            $category = MedicationCategory::find($cat_id);
            if($category)
            {
                $category->id = $cat_id;
                $category->category_name = $category_name[$key];
                $category->save();
            }
            else{
                $categorySave = new MedicationCategory();
                $categorySave->id = $cat_id;
                $categorySave->category_name = $category_name[$key];
                $categorySave->save();
            }

            ProductCategory::create([
                'product_id' => $product_id,
                'category_id' => $cat_id
            ]);
        }
    }
    public function getPlansById(PlanV1 $plan)
    {
        return response()->json($plan);
    }
    public function getProductCategories(Request $request)
    {
        $cate = MedicationCategory::all();
        return response()->json(['categories' =>  $cate]);
    }

    public function deletePatientRecord()
    {
        $user = Auth::guard('patient')->user();
        Appointment::where("patient_id", $user->id)->orderBy('id', 'desc')->delete();
        Cart::where("patient_id", $user->id)->orderBy('id', 'desc')->delete();
        PatientRegActivity::where("patient_id", $user->id)->orderBy('id', 'desc')->delete();
        Plan::where("patient_id", $user->id)->orderBy('id', 'desc')->delete();
        //PlanV1::where("patient_id", $user->id)->orderBy('id', 'desc')->delete();


        $patient = Patient::where("id", $user->id)->delete();

        return response()->json(['message' => "Record Deleted"], 200);
    }

    public function getSetting(Request $request)
    {
        return response()->json(Setting::first());
    }
    public function storePatientPlan(Request $request)
    {
        $user = Auth::guard('patient')->user();

        $request->validate([
            'plan_id' => 'required|exists:plans_v1,id',
        ]);

        $patientPlan = PatientPlan::create([
            'patient_id' => $user->id,
            'plan_id' => $request->plan_id,
        ]);

        return response()->json($patientPlan, 201);
    }
    public function getPatientPlan()
    {
        $user = Auth::guard('patient')->user();
        $patientPlans = PatientPlan::with('plan', 'patient')->where("patient_id", $user->id)->get();

        $response = $patientPlans->map(function ($patientPlan) {
            return [
                'patient_id' => $patientPlan->patient_id,
                'patient' => $patientPlan->patient,
                'plan_id' => $patientPlan->plan_id,
                'plan' => $patientPlan->plan,
            ];
        });

        return response()->json(['plans' => $response]);
    }
    public function getNotification()
    {
        $user = Auth::guard('patient')->user();
        $notification = Notification::where("patient_id", $user->id)->get();
        return response()->json(['notification' => $notification]);
    }
    public function getLabKit()
    {
        $kit = LabKit::all();
        return response()->json(['kit' => $kit], 200);
    }
}
