<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\CalenderService;
use App\Models\DiscussionService;
use App\Models\OpenCalendar;
use Illuminate\Support\Facades\Auth;
use App\Models\ServiceSchedule;
use App\Models\ScheduleWorktime;
use App\Models\WorkSlot;
use App\Models\OpenCalendarSchedule;

class CalenderServiceController extends Controller
{
    // get calendar service (API GET)
    public function index($id = null)
    {
        $user = Auth::user();
        if ($id != null) {
            $user = \App\Models\User::find($id);
        }
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        if ($calendar_service == null) {
            return [];
        }


        if (isset($calendar_service->type) && $calendar_service->type == 1) {


            foreach ($calendar_service->service_schedule as $service_schedule) {
                $service_schedule->schedule_worktime;
                foreach ($service_schedule->schedule_worktime as $worktime) {
                    $worktime->work_slots;
                }
            }
        } else {
            $calendar_service->open_calendar = OpenCalendar::where('user_id', $user->id)->get();
            foreach ($calendar_service->open_calendar as $schedules) {
                $schedules->open_calendar_schedule;
            }
        }


        return $calendar_service;
    }

    function isOverlaping($timeArray)
    {
        $isOverlaping = false;
        $count = count($timeArray);
        for ($i = 0; $i < $count; $i++) {
            for ($j = $i + 1; $j < $count; $j++) {
                if ($timeArray[$i]['start_time'] < $timeArray[$j]['end_time'] && $timeArray[$i]['end_time'] > $timeArray[$j]['start_time']) {
                    $isOverlaping = true;
                    break;
                }
            }
        }
        return $isOverlaping;
    }


    public function store(Request $request)
    {
        $user = Auth::user();
        $calendarReq = (object)  $request->calendar_service;
        // user has already created a calendar service
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        //get discussion_services
        $discussion_services = DiscussionService::where('user_id', $user->id)->first();

        //  dd($discussion_services);

        if ($discussion_services != null) {
            $daysArray = $discussion_services->days ? NULL : $discussion_services->days;
            $discussionDays = is_array($daysArray) ? $daysArray : json_decode($discussion_services->days);
            $discussiondaySchedules = [];
            foreach ($discussionDays as $day) {
                $timeArray = ['start_time' => strtotime(date('Y-m-d') . " " . $discussion_services->start_time), 'end_time' => strtotime(date('Y-m-d') . " " . $discussion_services->end_time)];
                $discussiondaySchedules[$day][] = $timeArray;
            }
        } else {
            $discussiondaySchedules = [];
        }

        if ($calendar_service == null) {
            $calendar_service = new CalenderService();
        }
        $calendar_service->user_id = $user->id;
        $calendar_service->type = $calendarReq->calendar_type ?? 0;
        $calendar_service->user_id = $user->id;
        $calendar_service->time_per_slot = $calendarReq->time_per_slot ?? 0;
        $calendar_service->gap_between_slots = $calendarReq->gap_between_slots ?? 0;
        $calendar_service->paid_by = $calendarReq->paid_by ?? '';
        $calendar_service->charge = $calendarReq->charge ?? 0;
        $calendar_service->charge_per = $calendarReq->charge_per ?? '';
        $calendar_service->clients_per_slot = $calendarReq->clients_per_slot ?? 0;
        $calendar_service->save();

        // delete all service schedules
        // $calendar_service->service_schedule()->delete();

        if ($calendarReq->calendar_type == 1) {

            $scheduleList = $calendarReq->schedules;
            $daySchedules = [];

            foreach ($scheduleList as $k => $v) {
                $daysDtls = $v['days'];
                foreach ($daysDtls as $day) {
                    $timeArray = ['start_time' => strtotime(date('Y-m-d') . " " . $v['schedule_start_time']), 'end_time' => strtotime(date('Y-m-d') . " " . $v['schedule_end_time'])];
                    $daySchedules[$day][] = $timeArray;
                    $discussiondaySchedules[$day][] = $timeArray;
                }
            }
            //
            $isOverlapping = 0;
            $resp = [];
            foreach ($daySchedules as $day => $timeArray) {
                // check $timeArray is overlaping or not
                $isOverlapping = $this->isOverlaping($timeArray);
                $resp[] = ['day' => $day, 'isOverlapping' => $isOverlapping ? 1 : 0];
            }

            $isOverlapping = max(array_column($resp, 'isOverlapping'));
            if ($isOverlapping == 1) {
                return ['message' => 'Time is overlapping.', 'status' => 'error'];
            }

            $resp = [];
            foreach ($discussiondaySchedules as $day => $timeArray) {
                // check $timeArray is overlaping or not
                $isOverlapping = $this->isOverlaping($timeArray);
                $resp[] = ['day' => $day, 'isOverlapping' => $isOverlapping ? 1 : 0];
            }

            $isOverlapping = max(array_column($resp, 'isOverlapping'));
            if ($isOverlapping == 1) {
                return ['message' => 'Time is overlapping with Discussion service.', 'status' => 'error'];
            }




            foreach ($calendarReq->schedules as $schedule) {
                $service_schedule = null;



                if (isset($schedule['id']) && $schedule['id'] != null) {
                    $service_schedule = ServiceSchedule::where('id', $schedule['id'])
                        ->where('user_id', $user->id)->first();
                } else {

                    $service_schedule = ServiceSchedule::where('calendar_service_id', $calendar_service->id)
                        ->where('user_id', $user->id)
                        ->where('schedule_name', $schedule['schedule_name'])
                        ->first();
                }

                if ($service_schedule == null) {
                    $service_schedule = new ServiceSchedule();
                }
                if ($service_schedule == null) {
                    return ['message' => 'Service schedule not found.', 'status' => 'error'];
                }



                $days = $schedule['days'];
                // dd($days);

                $service_schedule->calendar_service_id = $calendar_service->id;
                $service_schedule->user_id = $user->id;
                $service_schedule->schedule_name = $schedule['schedule_name'];
                $service_schedule->days = json_encode($schedule['days']);
                $service_schedule->schedule_start_time = $schedule['schedule_start_time'] ?? "00:00:00";
                $service_schedule->schedule_end_time = $schedule['schedule_end_time'];
                $service_schedule->time_per_session = $schedule['time_per_session'];
                $service_schedule->number_of_sessions = $schedule['number_of_sessions'];
                $service_schedule->gap_between_sessions = $schedule['gap_between_sessions'];
                $service_schedule->clients_per_session = $schedule['clients_per_session'];
                $service_schedule->calendar_visibility = $schedule['calendar_visibility'];
                $service_schedule->calendar_visibility_users = json_encode($schedule['calendar_visibility_users']);
                $service_schedule->charges_per_session = $schedule['charges_per_session'];
                $service_schedule->paid_by = $schedule['paid_by'];
                // prepaid_hours
                $service_schedule->prepaid_hours = $schedule['prepaid_hours'] ?? 0;
                $service_schedule->charges_per = $schedule['charges_per'];
                $service_schedule->allow_booking_after = $schedule['allow_booking_after'];
                $service_schedule->save();

                // delete all schedule worktimes
                $service_schedule->schedule_worktime()->delete();
                // create schedule worktimes
                foreach ($schedule['schedule_worktime'] as $worktime) {
                    $schedule_worktime = new ScheduleWorktime();
                    $schedule_worktime->schedule_id = $service_schedule->id;
                    $schedule_worktime->start_time = $worktime['start_time'];
                    $schedule_worktime->end_time = $worktime['end_time'];
                    $schedule_worktime->save();
                }
            }

            $calendar_service->service_schedule;
            foreach ($calendar_service->service_schedule as $service_schedule) {
                $service_schedule->schedule_worktime;
            }
            return $calendar_service;
        } else {

            //  $open_calendar = new OpenCalendar();


            // check any days overlapping time
            // $openCalendarDays = [];
            foreach ($calendarReq->schedules as $k => $v) {
                //   dd($v);
                $days = $v['days'];
                if (!is_array($days)) {
                    $days = json_decode($days);
                }


                foreach ($days as $day) {
                    $timeArray = ['start_time' => strtotime(date('Y-m-d') . " " . $v['start_time']), 'end_time' => strtotime(date('Y-m-d') . " " . $v['end_time'])];
                    $discussiondaySchedules[$day][] = $timeArray;
                }
            }

            $isOverlapping = 0;
            $resp = [];
            foreach ($discussiondaySchedules as $day => $timeArray) {
                // check $timeArray is overlaping or not
                $isOverlapping = $this->isOverlaping($timeArray);
                $resp[] = ['day' => $day, 'isOverlapping' => $isOverlapping ? 1 : 0];
            }

            $isOverlapping = max(array_column($resp, 'isOverlapping'));
            if ($isOverlapping == 1) {
                return ['message' => 'Time is overlapping With Discussion', 'status' => 'error'];
            }


            foreach ($calendarReq->schedules as $k => $schedule) {

                $schedule = (object) $schedule;
                $open_calendar = null;
                // dd($schedule);
                // open calendar with id
                if (isset($schedule->id)) {
                    $open_calendar = OpenCalendar::where('id', $schedule->id)->first();
                } else {
                    $open_calendar = OpenCalendar::where('calendar_service_id', $calendar_service->id)
                        ->where('user_id', $user->id)->first();
                }

                if ($open_calendar == null) {

                    $schedule->id = null;
                    $open_calendar = null;
                }



                $days = $schedule->days;
                //dd($days);

                if ($days == null) {
                    return [
                        'message' => 'Please select at least one day',
                        'status' => 'error'
                    ];
                }

                // $days is not an array
                if (!is_array($days)) {
                    return [
                        'message' => 'Please select at least one day',
                        'status' => 'error'
                    ];
                }


                // dd($days);
                // service schedule exists
                $opencalendarExists = OpenCalendar::where('user_id', $user->id)
                    ->where(function ($query) use ($days) {
                        //  $days = json_decode($days, true);
                        foreach ($days as $day) {
                            $query->orWhereJsonContains('days',  $day);
                        }
                    })
                    ->first();

                if ($opencalendarExists && (!isset($schedule->id) or $schedule->id == null)) {
                    return [
                        'message' => 'You already have a schedule for the selected days, please update.',
                        'status' => 'error'
                    ];
                }

                //  $open_calendar = OpenCalendar::where('user_id', $user->id)->first();
                if ($open_calendar == null) {
                    $open_calendar = new OpenCalendar();
                }

                $open_calendar->days = json_encode($schedule->days);
                $open_calendar->calendar_service_id = $calendar_service->id;
                $open_calendar->user_id = $user->id;
                $open_calendar->start_time = $schedule->start_time;
                $open_calendar->end_time = $schedule->end_time;
                $open_calendar->paid_by = $schedule->paid_by;
                $open_calendar->allow_booking_after = $schedule->allow_booking_after;
                $open_calendar->calendar_visibility = $schedule->calendar_visibility;
                $open_calendar->calendar_visibility_users = json_encode($schedule->calendar_visibility_users);
                $open_calendar->prepaid_hours = $schedule->prepaid_hours ?? 0;

                // dd($open_calendar);
                $open_calendar->save();

                // delete all open calendar schedules
                $open_calendar_schedules = OpenCalendarSchedule::where('open_calendar_id', $open_calendar->id)->get();
                foreach ($open_calendar_schedules as $open_calendar_schedule) {
                    $open_calendar_schedule->delete();
                }

                // create open calendar schedules
                foreach ($schedule->schedules as $calendar_schedule) {
                    $open_calendar_schedule = new OpenCalendarSchedule();
                    //  dd($open_calendar_schedule);
                    $open_calendar_schedule->calendar_service_id = $calendar_service->id;
                    $open_calendar_schedule->open_calendar_id = $open_calendar->id;
                    $open_calendar_schedule->user_id = $user->id;
                    $open_calendar_schedule->time_per_session = $calendar_schedule['time_per_session'] ?? 0;
                    $open_calendar_schedule->type = $calendar_schedule['type'];
                    $open_calendar_schedule->price = $calendar_schedule['price'];

                    $open_calendar_schedule->save();
                }
            }
        }

        $calendar_service->open_calendar = OpenCalendar::where('user_id', $user->id)->get();
        foreach ($calendar_service->open_calendar as $open_calendar) {
            $open_calendar->open_calendar_schedule;
        }
        return $calendar_service;
    }



    public function saveServiceSchedule(Request $request)
    {

        $calendarReq = (object) $request->calendar_service;


        $user = Auth::user();
        $calendar_service = CalenderService::where('user_id', $user->id)->first();
        //   dd($request->id);
        $service_schedule = ServiceSchedule::where('id', $calendarReq->id)->first();

        if ($service_schedule == null) {
            $service_schedule = new ServiceSchedule();
        } else {
            $service_schedule->schedule_worktime()->delete();
        }
        $days = $calendarReq->days;
        // dd($calendarReq);
        // check this days already exist or not
        // $service_schedule_exist = ServiceSchedule::where('calendar_service_id', $calendar_service->id)
        //     ->where(function ($query) use ($days) {
        //         $days = json_decode($days, true);
        //         foreach ($days as $day) {
        //             $query->orWhereJsonContains('days',  $day);
        //         }
        //     })
        //     ->first();

        // if ($service_schedule_exist != null && $service_schedule_exist->id != $calendarReq->id) {
        //     return ['message' => 'This day(s) already selected.', 'status' => 'error'];
        // }

        //if $request->id not exists, check ServiceSchedule count already created
        if (!$calendarReq->id) {
            $service_schedule_count = ServiceSchedule::where('calendar_service_id', $calendar_service->id)->count();
            if ($service_schedule_count >= 7) {
                return ['message' => 'You can not create more than 6 schedules.', 'status' => 'error'];
            }
        }



        $service_schedule->calendar_service_id = $calendar_service->id;
        $service_schedule->user_id = $user->id;
        $service_schedule->days = $calendarReq->days;
        // schedule_name
        $service_schedule->schedule_name = $calendarReq->schedule_name;
        $service_schedule->schedule_start_time = $calendarReq->schedule_start_time;
        $service_schedule->schedule_end_time = $calendarReq->schedule_end_time;
        $service_schedule->time_per_session = $calendarReq->time_per_session;
        $service_schedule->number_of_sessions = $calendarReq->number_of_sessions;
        $service_schedule->gap_between_sessions = $calendarReq->gap_between_sessions;
        $service_schedule->clients_per_session = $calendarReq->clients_per_session;
        $service_schedule->calendar_visibility = $calendarReq->calendar_visibility;
        $service_schedule->calendar_visibility_users = $calendarReq->calendar_visibility_users;
        $service_schedule->charges_per_session = $calendarReq->charges_per_session;
        $service_schedule->paid_by = $calendarReq->paid_by;
        $service_schedule->charges_per = $calendarReq->charges_per;
        $service_schedule->allow_booking_after = $calendarReq->allow_booking_after;
        $service_schedule->save();

        // create schedule worktimes
        foreach ($calendarReq->schedule_worktime as $worktime) {
            $schedule_worktime = new ScheduleWorktime();
            $schedule_worktime->schedule_id = $service_schedule->id;
            $schedule_worktime->start_time = $worktime['start_time'];
            $schedule_worktime->end_time = $worktime['end_time'];
            $schedule_worktime->save();
        }
        $service_schedule->schedule_worktime;
        return $service_schedule;
    }

















    // store calendar service (API POST)
    public function store1(Request $request)
    {

        $user = Auth::user();

        // user has already created a calendar service
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        if ($calendar_service == null) {
            $calendar_service = new CalenderService();
        }
        $calendar_service->user_id = $user->id;
        $calendar_service->time_per_slot = $request->time_per_slot ?? 0;
        //gap_between_slots
        $calendar_service->gap_between_slots = $request->gap_between_slots ?? 0;
        $calendar_service->paid_by = $request->paid_by ?? '';
        $calendar_service->charge = $request->charge ?? 0;
        $calendar_service->charge_per = $request->charge_per ?? '';
        $calendar_service->clients_per_slot = $request->clients_per_slot ?? 0;
        $calendar_service->save();


        // check if service schedule is empty
        if ($calendar_service->service_schedule()->count() == 0) {
            // create 3 default service schedules
            foreach (range(1, 3) as $i) {
                $service_schedule = new ServiceSchedule();
                $service_schedule->calendar_service_id = $calendar_service->id;
                $service_schedule->user_id = $user->id;
                $service_schedule->schedule_name = 'Schedule ' . $i;
                $service_schedule->save();
            }
        }
        $calendar_service->service_schedule;
        return response()->json($calendar_service);
    }


    // create service_schedules (API POST)
    public function updateServiceSchedules(Request $request)
    {
        $user = Auth::user();
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        $service_schedule_id = $request->schedule_id ?? 0;
        $service_schedule = ServiceSchedule::find($service_schedule_id);

        $service_schedule->schedule_name = $request->schedule_name ?? '';
        $service_schedule->save();
    }


    public function enableCalendarService(Request $request)
    {

        $user = Auth::user();

        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        if ($calendar_service == null) {

            $calendar_service = new CalenderService();
        }

        $calendar_service->user_id = $user->id;
        $calendar_service->time_per_slot = $request->time_per_slot ?? 0;
        $calendar_service->gap_between_slots = $request->gap_between_slots ?? 0;
        $calendar_service->paid_by = $request->paid_by ?? '';
        $calendar_service->charge = $request->charge ?? 0;
        $calendar_service->charge_per = $request->charge_per ?? '';
        $calendar_service->clients_per_slot = $request->clients_per_slot ?? 0;
        $calendar_service->save();

        // create schedule
        $schedules = $request->schedules ?? [];
        foreach ($schedules as $k => $v) {
            if (isset($v->id) && $v->id) {
                $schedule = ServiceSchedule::find($v->id);
            } else {
                $schedule = new ServiceSchedule();
            }


            $schedule->calendar_service_id = $calendar_service->id;
            $schedule->schedule_name = $v['name'] ?? '';
            $schedule->days = json_encode($v['days']) ?? "[]";
            $schedule->user_id = $user->id;
            $schedule->save();


            // check ScheduleWorktime is empty
            $scheduleCount = $schedule->schedule_worktime()->count();


            // create schedule worktime
            $worktimes = $v['worktime'] ?? [];
            foreach ($worktimes as $k2 => $v2) {



                if (isset($v2->id) && $v2->id) {
                    $worktime = ScheduleWorktime::find($v2->id);
                } else {
                    if ($scheduleCount > ($k2 + 1)) {
                        // error, Workitime ID is missing
                        return response()->json(['message' => 'Workitime ID is missing', 'status' => 'error'], 400);
                    }
                    $worktime = new ScheduleWorktime();
                }

                $worktime->schedule_id = $schedule->id;
                $worktime->title = $v2['title'] ?? '';
                $worktime->start_time = $v2['start_time'] ?? '00:00:00';
                $worktime->end_time = $v2['end_time'] ?? '00:00:00';
                $worktime->save();

                // create schedule worktime slots
                $slots = $v2['slots'] ?? [];
                foreach ($slots as $k3 => $v3) {
                    if (isset($v3->id) && $v3->id) {
                        $slot = WorkSlot::find($v3->id);
                    } else {
                        $slot = new WorkSlot();
                    }
                    $slot->schedule_id = $schedule->id;
                    $slot->user_id = $user->id;
                    $slot->worktime_id = $worktime->id;
                    $slot->title = $v3['title'] ?? '';
                    $slot->start_time = $v3['start_time'] ?? '00:00:00';
                    $slot->end_time = $v3['end_time'] ?? '00:00:00';
                    $slot->save();
                }
            }
        }
        $calendar_service->service_schedule;

        foreach ($calendar_service->service_schedule as $k => $v) {
            $v->schedule_worktime;
            foreach ($v->schedule_worktime as $k2 => $v2) {
                $v2->work_slots;
            }
        }



        return response()->json($calendar_service);


        // dd($request->all());
    }



    // create work time (API POST) under service schedule
    public function updateWorkTime(Request $request)
    {
        $user = Auth::user();
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        $service_schedule_id = $request->schedule_id ?? 0;
        $service_schedule = ServiceSchedule::find($service_schedule_id);

        $worktime_id = $request->worktime_id ?? 0;
        if ($worktime_id != 0) {
            $worktime = $service_schedule->schedule_worktime()->find($worktime_id);

            $worktime->start_time = $request->start_time ?? '00:00:00';
            $worktime->end_time = $request->end_time ?? '00:00:00';
        } else {

            // check count of worktime
            if ($service_schedule->schedule_worktime()->count() == 3) {
                return response()->json(['message' => 'You can not add more than 3 work times.', 'status' => 'error']);
            }

            $arr = [];
            $arr['start_time'] = $request->start_time ?? '00:00:00';
            $arr['end_time'] = $request->end_time ?? '00:00:00';

            $worktime = $service_schedule->schedule_worktime()->create($arr);
        }
        //dd($worktime_id);


        if (isset($request->days)) {
            if (is_array($request->days)) {
                $service_schedule->days = $request->days;
            } else {
                $service_schedule->days = json_decode($request->days);
            }
            $service_schedule->save();
        }



        // does request have work_slots?
        if ($request->work_slots) {
            // delete all work_slots
            $worktime->work_slots()->delete();

            if (!is_array($request->work_slots)) {
                $request->work_slots = json_decode($request->work_slots, true);
            }


            // create new work_slots
            foreach ($request->work_slots as $work_slot) {
                $work_slot = $worktime->work_slots()->create([
                    'start_time' => $work_slot['start_time'],
                    'end_time' => $work_slot['end_time'],
                    'schedule_id' => $service_schedule->id,
                    'user_id' => $user->id,
                    'title' => $work_slot['title'] ?? '',
                ]);
            }
        }

        $worktime->load('work_slots');
        return response()->json($worktime);
    }


    // delete work time (API POST) under service schedule
    public function deleteWorkTime(Request $request)
    {
        $user = Auth::user();
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        $service_schedule_id = $request->schedule_id ?? 0;
        $service_schedule = ServiceSchedule::find($service_schedule_id);

        $worktime_id = $request->worktime_id ?? 0;
        $worktime = $service_schedule->schedule_worktime()->find($worktime_id);
        $worktime->delete();

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


    // create work slot (API POST) under service schedule
    public function updateWorkSlot(Request $request)
    {
        $user = Auth::user();
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        $service_schedule_id = $request->schedule_id ?? 0;
        $service_schedule = ServiceSchedule::find($service_schedule_id);

        $work_slot_id = $request->work_slot_id ?? 0;
        if ($work_slot_id == 0) {
            $work_slot = $service_schedule->work_slots()->find($work_slot_id);
        } else {
            $work_slot = $service_schedule->work_slots()->create();
        }


        $work_slot->schedule_id = $service_schedule->id;
        $work_slot->worktime_id = $request->worktime_id ?? 0;
        $work_slot->user_id = $user->id;
        $work_slot->title = $request->title ?? '';
        $work_slot->start_time = $request->start_time ?? '00:00:00';
        $work_slot->end_time = $request->end_time ?? '00:00:00';
        $work_slot->save();

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

    public function deleteSchedule(Request $request, $id)
    {
        $user = Auth::user();
        $calendar_service = CalenderService::where('user_id', $user->id)->first();

        $service_schedule_id = $id ?? 0;
        $service_schedule = ServiceSchedule::find($service_schedule_id);


        foreach ($calendar_service->service_schedule as $service_schedule) {
            $service_schedule->schedule_worktime;
            foreach ($service_schedule->schedule_worktime as $worktime) {
                $worktime->work_slots;
            }
        }

        $service_schedule->delete();

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