<?php

namespace App\Http\Controllers\Admin\Api;

use App\Classes\Constant;
use App\Http\Controllers\Controller;
use App\Models\Telemedpro;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use App\Models\Appointment;
use App\Models\Cart;
use App\Models\PatientNote;
use App\Models\PatientPrescription;
use App\Models\Subscription;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Routing\UrlGenerator;
use Yajra\DataTables\DataTables;
use Illuminate\Auth\Access\AuthorizationException;

class TelemedProAgentController extends Controller
{
    protected $url;
    protected $user;
    public function __construct(UrlGenerator $url)
    {
        $this->url = $url;
        $this->user = Auth::guard('admin')->user();
    }
    public function register(Request $request)
    {
        try {
            $this->authorizeForUser($this->user, 'add', new Telemedpro);
            // Validate the request data
            $validator = Validator::make($request->all(), [
                'first_name' => ['required', 'string', 'max:255'],
                'last_name' => ['required', 'string', 'max:255'],
                'email' => ['required', 'string', 'email', 'max:255', 'unique:telemed_pros'],
                'password' => ['required', 'string', 'min:8'],
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'errors' => $validator->errors()
                ], 422);
            }

            $first_name = $request->input('first_name');
            $last_name = $request->input('last_name');
            $email = $request->input('email');
            $digits = 4;
            $code = rand(pow(10, $digits - 1), pow(10, $digits) - 1);

            // Prepare data for creating a new Telemedpro user
            $userData = [
                'name' => $first_name . " " . $last_name,
                'first_name' => $first_name,
                'last_name' => $last_name,
                'email' => $email,
                'password' => Hash::make($request->input('password')),
                'status' => 1,
                'email_verification' => $code,
                'home_address' => $request->input('home_address'),
                'city' => $request->input('city'),
                'state' => $request->input('state'),
                'zip_code' => $request->input('zip_code'),
                'medical_license_number' => json_encode($request->input('medical_license_number')), // Convert to JSON string
                'years_of_experience' => $request->input('years_of_experience'),
                'specialty' => $request->input('specialty'),
                'gender' => $request->input('gender'),
                'practice_state' => json_encode($request->input('practice_state')), // Convert to JSON string
                'phone_number' => $request->input('phone'),
                'availability_from' => $request->input('availabilityFrom'),
                'availability_to' => $request->input('availabilityTo'),
            ];

            // Create the new user
            $user = Telemedpro::create($userData);

            // Create an auth token
            $token = $user->createToken('auth_token')->plainTextToken;

            return response()->json([
                'user' => $user,
                'token' => $token,
                'message' => 'User registered successfully',
            ], 201);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function details($id)
    {
        try {
            $this->authorizeForUser($this->user, 'view', new Telemedpro);
            return response()->json([
                'provider' => Telemedpro::find($id)

            ], 201);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }


    public function telemedProFullDetail(Telemedpro $telemed)
    {
        try {
            $this->authorizeForUser($this->user, 'view', new Telemedpro);
            $upcomingMeetings = Cart::select(
                'carts.id as order_id',
                'appointments.id',
                'appointments.patient_id',
                'appointments.appointment_time',
                'appointments.appointment_date',
                DB::raw(
                    'CONCAT(patients.first_name, " " , patients.last_name) as patient_name'
                )
            )
                ->join('appointments', 'appointments.id', 'carts.appointment_id')
                ->leftJoin('patients', 'patients.id', 'appointments.patient_id')
                ->where("appointments.telemed_pros_id", $telemed->id)
                ->where('appointments.appointment_date', ">=", Carbon::now()->format("Y-m-d"))
                ->get();
            $completedMeetings = Cart::select(
                'carts.id as order_id',
                'appointments.patient_id',
                'appointments.appointment_time',
                'appointments.appointment_date',
                'appointments.start_time',
                'appointments.end_time',
                'telemed_pros.name as provider_name',
                'appointments.telemed_pros_id as provider_id',

                DB::raw(
                    'CONCAT(patients.first_name, " " , patients.last_name) as patient_name'
                )
            )
                ->join('appointments', 'appointments.id', 'carts.appointment_id')
                ->leftJoin('patients', 'patients.id', 'appointments.patient_id')
                ->leftJoin('telemed_pros', 'telemed_pros.id', 'appointments.telemed_pros_id')
                //->leftJoin('carts', 'appointments.id', 'carts.appointment_id')
                ->where("appointments.telemed_pros_id", $telemed->id)
                ->where('appointments.start_time', "!=", null)
                ->where('appointments.end_time', "!=", null)
                ->get();
            $patientNotes = PatientNote::select(
                'patient_notes.note',
                'patient_notes.note_type',
                'telemed_pros.name as provider_name',
                'telemed_pros.id as provider_id',
                'patient_notes.created_at',
                'carts.id as order_id',
                'patient_notes.created_by_id',
                'patient_notes.created_by_type'
            )
                ->leftJoin('telemed_pros', 'patient_notes.telemed_pros_id', 'telemed_pros.id')
                ->leftJoin('appointments', 'patient_notes.appointment_id', 'appointments.id')
                ->leftJoin('carts', 'appointments.id', 'carts.appointment_id')
                ->where("appointments.telemed_pros_id", $telemed->id)
                ->get();

            foreach ($patientNotes as $notes) {
                if ($notes->note_type != 'Notes')
                    $notes->note = $this->url->to("assets/files/" . $notes->patient_id . ".png");
                else
                    $notes->note = $notes->note;
            }
            $patientPrescription = PatientPrescription::select(
                'patient_prescription.*',
                'telemed_pros.name as provider_name',
                'prescriptions.*',
                'carts.id as order_id'
            )
                ->leftJoin('appointments', 'patient_prescription.appointment_id', 'appointments.id')
                ->leftJoin('carts', 'appointments.id', 'carts.appointment_id')
                ->leftJoin('telemed_pros', 'appointments.telemed_pros_id', 'telemed_pros.id')
                ->leftJoin('prescriptions', 'prescriptions.id', 'patient_prescription.prescription_id')
                ->where('appointments.telemed_pros_id', $telemed->id)->get();
            return response()->json([
                'telemed' => $telemed,
                'upcomingMeetings' => $upcomingMeetings,
                'completed_meetings' => $completedMeetings,
                'notes' => $patientNotes,
                'prescriptions' => $patientPrescription,

            ]);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function telemedList(Request $request)
    {
        try {
            $this->authorizeForUser($this->user, 'list', new Telemedpro);
            // Get filter inputs from the request
            $practiceState = $request->input('practice_state');
            $gender = $request->input('gender');
            $specialty = $request->input('specialty');
            $state = $request->input('state');
            $search = $request->input('search');
            $availabilityFrom = $request->input('availability_from');
            $availabilityTo = $request->input('availability_to');

            // Build the query with optional filters and join
            $query = Telemedpro::query()
                ->leftJoin('appointments', 'telemed_pros.id', '=', 'appointments.telemed_pros_id')
                ->leftJoin('carts', 'appointments.id', '=', 'carts.appointment_id')
                ->select(
                    'telemed_pros.id',
                    'telemed_pros.name',
                    'telemed_pros.first_name',
                    'telemed_pros.last_name',
                    'telemed_pros.email',
                    'telemed_pros.is_busy',
                    'telemed_pros.recording_switch',
                    'telemed_pros.ai_switch',
                    'telemed_pros.status',
                    'telemed_pros.practice_state',
                    'telemed_pros.phone_number',
                    'telemed_pros.gender',
                    'telemed_pros.specialty',
                    'telemed_pros.home_address',
                    'telemed_pros.medical_license_number',
                    'telemed_pros.years_of_experience',
                    'telemed_pros.email_verification',
                    'telemed_pros.city',
                    'telemed_pros.state',
                    'telemed_pros.zip_code',
                    'telemed_pros.availability_to',
                    'telemed_pros.availability_from'
                )
                ->selectRaw('COUNT(DISTINCT carts.id) as meeting_count')
                ->groupBy(
                    'telemed_pros.id',
                    'telemed_pros.name',
                    'telemed_pros.first_name',
                    'telemed_pros.last_name',
                    'telemed_pros.email',
                    'telemed_pros.is_busy',
                    'telemed_pros.recording_switch',
                    'telemed_pros.ai_switch',
                    'telemed_pros.status',
                    'telemed_pros.practice_state',
                    'telemed_pros.phone_number',
                    'telemed_pros.gender',
                    'telemed_pros.specialty',
                    'telemed_pros.home_address',
                    'telemed_pros.medical_license_number',
                    'telemed_pros.years_of_experience',
                    'telemed_pros.email_verification',
                    'telemed_pros.city',
                    'telemed_pros.state',
                    'telemed_pros.zip_code',
                    'telemed_pros.availability_to',
                    'telemed_pros.availability_from'
                );

            if ($practiceState && $practiceState !== 'All') {
                $query->where('telemed_pros.practice_state', $practiceState);
            }
            if ($gender && $gender !== 'All') {
                $query->where('telemed_pros.gender', $gender);
            }
            if ($specialty && $specialty !== 'All') {
                $query->where('telemed_pros.specialty', $specialty);
            }
            if ($state && $state !== 'All') {
                $query->where('telemed_pros.state', $state);
            }
            if ($availabilityFrom && $availabilityFrom !== 'All') {
                $query->where('telemed_pros.availability_from', '<=', $availabilityFrom);
            }
            if ($availabilityTo && $availabilityTo !== 'All') {
                $query->where('telemed_pros.availability_to', '>=', $availabilityTo);
            }
            return DataTables::of($query)
                ->addColumn('availability_from', function ($telemedpro) {
                    return $telemedpro->availability_from;
                })
                ->addColumn('availability_to', function ($telemedpro) {
                    return $telemedpro->availability_to;
                })
                ->addColumn('specialty', function ($telemedpro) {
                    return $telemedpro->specialty;
                })
                ->addColumn('meeting_count', function ($telemedpro) {
                    return $telemedpro->meeting_count;
                })
                ->make(true);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }

    public function telemed(Telemedpro $telemed)
    {
        return response()->json([
            'patient' => $telemed
        ]);
    }
    public function telemedDelete(Telemedpro $telemed)
    {
        try {
            $this->authorizeForUser($this->user, 'delete', new Telemedpro);
            $telemed->delete();
            return response()->json([
                'message' => "Deleted Successfully"
            ]);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function telemedUpdate(Telemedpro $telemed, Request $request)
    {
        try {
            $this->authorizeForUser($this->user, 'delete', new Subscription);
            $first_name = $request->input('first_name');
            $last_name = $request->input('last_name');
            $email = $request->input('email');


            $telemed->name = $first_name . " " . $last_name;
            $telemed->first_name = $first_name;
            $telemed->last_name = $last_name;
            $telemed->email = $email;
            $telemed->password = Hash::make($request->input('password'));
            $telemed->status = 1;
            $telemed->home_address = $request->input('home_address');
            $telemed->city = $request->input('city');
            $telemed->state = $request->input('state');
            $telemed->zip_code = $request->input('zip_code');
            $telemed->medical_license_number = json_encode($request->input('medical_license_number')); // Convert to JSON string
            $telemed->years_of_experience = $request->input('years_of_experience');
            $telemed->specialty = $request->input('specialty');
            $telemed->gender = $request->input('gender');
            $telemed->practice_state = json_encode($request->input('practice_state')); // Convert to JSON string
            $telemed->phone_number = $request->input('phone');
            $telemed->availability_from = $request->input('availabilityFrom');
            $telemed->availability_to = $request->input('availabilityTo');
            $telemed->save();
            return response()->json([
                'message' => 'Telemedpro updated successfully',
                'telemed' => $telemed
            ]);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function getMeetingHistoryTelemedpro(Telemedpro $telemedpro, $filter = '12_months')
    {
        try {
            $this->authorizeForUser($this->user, 'meeting_history', new Telemedpro);
            $currentMonth = Carbon::now();
            // Filter logic
            switch ($filter) {
                case 'current_month':
                    $startDate = $currentMonth->copy()->startOfMonth();
                    break;
                case '1_month':
                    $startDate = $currentMonth->copy()->subMonth()->startOfMonth();
                    break;
                case '2_months':
                    $startDate = $currentMonth->copy()->subMonths(2)->startOfMonth();
                    break;
                case '3_months':
                    $startDate = $currentMonth->copy()->subMonths(3)->startOfMonth();
                    break;
                case '6_months':
                    $startDate = $currentMonth->copy()->subMonths(6)->startOfMonth();
                    break;
                default: // Default to 12 months
                    $startDate = $currentMonth->copy()->subMonths(12)->startOfMonth();
            }
            $endDate = $currentMonth->endOfMonth();
            // Fetch patient names and appointment counts directly from the database
            $monthlyData = Appointment::select(
                'patient_id',
                'telemed_pros_id',
                'appointment_time',
                'appointment_date',
                'start_time',
                'end_time',
                'duration',
                'id'
            )
                ->where("telemed_pros_id", $telemedpro->id)
                ->whereNotNull("end_time")
                ->whereBetween('created_at', [$startDate, $endDate])
                ->get();
            $patients = [];
            foreach ($monthlyData as $dataPoint) {
                $patientName = $dataPoint->patient->first_name . " " . $dataPoint->patient->last_name; // Assuming 'name' is the field representing patient names
                /* $appointmentCount = $dataPoint->appointment_count; */
                $start_time = $dataPoint->start_time;
                $end_time = $dataPoint->end_time;
                $duration = $dataPoint->duration;
                $appointment_time = $dataPoint->appointment_time;
                $appointment_date = $dataPoint->appointment_date;
                $patient_id = $dataPoint->patient_id;
                $id = $dataPoint->id;

                $patients[] = [
                    'patient_name' => $patientName,
                    'appointment_time' => $appointment_time,
                    'appointment_date' => $appointment_date,
                    /* 'appointment_count' => $appointmentCount, */
                    'start_time' => $start_time,
                    'end_time' => $end_time,
                    'duration' => $duration,
                    'id' => $id,
                    'patient_id' => $patient_id,
                ];
            }
            return response()->json([
                'patients' => $patients,
            ]);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
}
