<?php

namespace App\Http\Controllers;

use App\Models\RosterTemplate;
use App\Models\EmpPersonalDetails;
use App\Models\EmpCompanyDetails;
use App\Models\RosterAssign;
use App\Models\LeaveRequest;
use App\Models\RosterHistory;
use App\Models\User;
use App\Models\EmpTeamsMember;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use DB;
use Carbon\Carbon;
use App\Jobs\SendEmailJob;
use App\Models\PublicHoliday;
use App\Traits\RosterTemplateTrait;
use App\Http\Controllers\Traits\EmailTrait;


class RosterTemplateController extends Controller
{
    use RosterTemplateTrait, EmailTrait;

    // function hasShiftConflict($shifts, $currentShift)
    // {

    //     $currentStartDateTime = Carbon::createFromFormat('H:i:s', $currentShift['roster_template']['start_time']);
    //     $currentEndDateTime = Carbon::createFromFormat('H:i:s', $currentShift['roster_template']['end_time']);

    //     foreach ($shifts as $shift) {
    //         if ($shift === $currentShift) {
    //             continue; // Skip checking against itself
    //         }

    //         $startDateTime = Carbon::createFromFormat('H:i:s', $shift['roster_template']['start_time']);
    //         $endDateTime = Carbon::createFromFormat('H:i:s', $shift['roster_template']['end_time']);

    //         // Check for overlap
    //         if ($currentStartDateTime < $endDateTime && $currentEndDateTime > $startDateTime) {
    //             return true; // Conflict found
    //         }
    //     }

    //     return false; // No conflicts found
    // }
    function hasShiftConflict($shifts, $currentShift)
    {
        // Ensure currentShift and its roster_template exist
        if (
            !isset($currentShift['roster_template']) ||
            empty($currentShift['roster_template']['start_time']) ||
            empty($currentShift['roster_template']['end_time'])
        ) {
            return false; // No conflict if data is invalid
        }

        $currentStartDateTime = Carbon::createFromFormat('H:i:s', $currentShift['roster_template']['start_time']);
        $currentEndDateTime = Carbon::createFromFormat('H:i:s', $currentShift['roster_template']['end_time']);

        foreach ($shifts as $shift) {
            // Ensure shift and its roster_template exist
            if (
                !isset($shift['roster_template']) ||
                empty($shift['roster_template']['start_time']) ||
                empty($shift['roster_template']['end_time'])
            ) {
                continue; // Skip invalid shifts
            }

            // Avoid comparing the same shift
            if ($shift['roster_template'] === $currentShift['roster_template']) {
                continue;
            }

            $startDateTime = Carbon::createFromFormat('H:i:s', $shift['roster_template']['start_time']);
            $endDateTime = Carbon::createFromFormat('H:i:s', $shift['roster_template']['end_time']);

            // Check for time overlap
            if ($currentStartDateTime < $endDateTime && $currentEndDateTime > $startDateTime) {
                return true; // Conflict found
            }
        }

        return false; // No conflicts found
    }

    public function index(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'start_date' => 'required',
            'end_date' => 'required',
            'scheduler_mode' => 'required',
            'user_type' => 'nullable',
            'selected_employee' => 'nullable'
        ]);
        $userTable = $this->getUserTable();
        if ($validator->fails()) {
            return $this->message($validator->errors()->first(), 404);
        } else {
            $validatedData =  $validator->validated();
            $dates_array =  $this->getDatesBetween($validatedData['start_date'], $validatedData['end_date']);

            // Generate dates with day names for proper frontend mapping
            $dates_with_info = $this->generateDatesWithDayNames($dates_array, $validatedData['scheduler_mode']);

            $selected_employee =   $request->selected_employee;

            $query = EmpCompanyDetails::query();
            $query->where('id', '!=', '1');
            if (!is_null($selected_employee) && count($selected_employee) > 0) {
                $query->whereIn('id', $selected_employee);
            }
            if ($validatedData['user_type'] == '0' || $validatedData['user_type'] == '1') {
                $query->where('user_type', $validatedData['user_type']);
            }
            $query->with(['empPersonalDetails' => function ($query) {
                $query->select('emp_id', 'first_name', 'middle_name', 'last_name', 'image');
            }]);
            if ($userTable === "customer") {
                $query->where('customer_id', Auth::user()->id)
                    ->where('workspace_id', Auth::user()->current_workspace_id);
            }
            if ($userTable === "emp") {
                $query->where('customer_id', auth()->user()->customer_id) // Assuming customer_id links employee to projects
                    ->where('workspace_id', auth()->user()->workspace_id);
            }



            if ($request->filled('pagination') || !empty($request->filters)) {
                $users = $this->searchFilterRecord($query, $request);
                $isPaginated = true;
            } else {
                $users = $query->select('id', 'user_type')->get();
                $isPaginated = false;
                $count = $query->count();
                $from = $request->input('from', 0);
                $per_page = $request->input('per_page', 10);
                // $query->offset($from)->limit($per_page);
                $query->orderBy('id', 'desc');
            }

            // Process shifts, holidays, and leaves for each user
            $user_data = [];
            foreach ($users as $user) {
                $user_shifts = [];
                if (!$user->empPersonalDetails) {
                    continue;  // Skip the user if they don't have personal details
                }
                foreach ($dates_array as $date) {
                    $shifts_of_this_box = RosterAssign::with('rosterTemplate', 'site')
                        ->where(['assign_to' => $user->id, 'schedule_date' => $date])
                        ->get();

                    $holiday = PublicHoliday::where('from', '<=', $date)
                        ->where('to', '>=', $date)
                        ->first();

                    $leave = LeaveRequest::where('employee_id', $user->id)
                        ->where('status', '!=', '2')
                        ->where('from', '<=', $date)
                        ->where('to', '>=', $date)
                        ->first();

                    $shifts = [];
                    foreach ($shifts_of_this_box as $shift) {
                        if ($shift->rosterTemplate) {
                            $shifts[] = [
                                'start_time' => $shift->rosterTemplate->start_time,
                                'end_time' => $shift->rosterTemplate->end_time,
                                'color_code' => $shift->rosterTemplate->color_code,
                                'template_id' => $shift->roster_template_id,
                                'conflict' => $this->hasShiftConflict($shifts_of_this_box, $shift),
                                'site_id' => $shift->site_id,
                                'site_title' => $shift->site ? $shift->site->title : null,
                            ];
                        }
                    }

                    $user_shifts[] = [
                        'date' => $date,
                        'holiday' => $holiday ? $holiday->title : null,
                        'leave' => $leave ? ($leave->leavepackage->title ?? null) : null,
                        'shifts' => $shifts
                    ];
                }

                $user_data[] = [
                    'id' => $user->id,
                    'user_type' => $user->user_type,
                    'personal_details' => $user->empPersonalDetails,
                    'shifts' => $user_shifts
                ];
            }

            $response_data = [
                'message' => 'Roster fetched successfully',
                'data' => [
                    'dates' => $dates_array,
                    'dates_with_info' => $dates_with_info,
                    'scheduler_mode' => $validatedData['scheduler_mode'],
                    'users' => $user_data,
                    'count' => $isPaginated ? $users->total() : $count,
                    'from' => $isPaginated ? $users->firstItem() : $from,
                    'per_page' => $isPaginated ? $users->perPage() : $per_page
                ]
            ];

            // Add pagination attributes if paginated
            if ($isPaginated) {
                $response_data['data']['pagination'] = [
                    'current_page' => $users->currentPage(),
                    'last_page' => $users->lastPage(),
                    'per_page' => $users->perPage(),
                    'total' => $users->total(),
                    'from' => $users->firstItem(),
                    'to' => $users->lastItem(),
                    'next_page_url' => $users->nextPageUrl(),
                    'prev_page_url' => $users->previousPageUrl(),
                    'first_page_url' => $users->url(1),
                    'last_page_url' => $users->url($users->lastPage())
                ];
            }

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


    public function inactive(Request $request)
    {
        $userTable = $this->getUserTable();
        $validator = Validator::make($request->all(), [
            'date' => 'required|date',
            'is_template' => 'required|boolean',
            'template_id' => 'nullable',
            'user_id' => 'nullable|exists:emp_company_details,id'
        ]);

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

        if ($request->is_template == 1) {
            if ($userTable === "customer") {
                $templates = RosterTemplate::where('is_saved', '1')->where('customer_id', Auth::user()->id)->where('status', 0)->where('workspace_id', Auth::user()->current_workspace_id)->get();
            }
            if ($userTable === "emp") {
                $templates = RosterTemplate::where('is_saved', '1')->where('customer_id', auth()->user()->customer_id)->where('status', 0)->where('workspace_id', auth()->user()->workspace_id)->get();
            }
            $templates_data = [];
            $i = 0;
            foreach ($templates as $t) {
                $templates_data[$i] = $t;
                $templates_data[$i]['start_time_am_pm'] = $this->AM_PM($t->start_time);
                $templates_data[$i]['end_time_am_pm'] = $this->AM_PM($t->end_time);
                $i++;
            }
            $data =  [
                'saved_templates' => $templates_data,
                'date' => $request->date,
            ];
        } else {
            $template = RosterTemplate::where('id', $request->template_id)->where('status', 0)->first();
            $data =  [
                'user_id' => $request->user_id,
                'date' => $request->date,
                'template' => $template
            ];
        }
        return $this->success($data, 'Get Data Successfully');
    }
    public function create(Request $request)
    {
        $userTable = $this->getUserTable();
        $validator = Validator::make($request->all(), [
            'date' => 'required|date',
            'is_template' => 'required|boolean',
            'template_id' => 'nullable',
            'user_id' => 'nullable|exists:emp_company_details,id'
        ]);

        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        }

        if ($request->is_template == 1) {
            if ($userTable === "customer") {
                $templates = RosterTemplate::where('is_saved', '1')->where('customer_id', Auth::user()->id)->where('status', 1)->where('workspace_id', Auth::user()->current_workspace_id)->get();
            }
            if ($userTable === "emp") {
                $templates = RosterTemplate::where('is_saved', '1')->where('customer_id', auth()->user()->customer_id)->where('status', 1)->where('workspace_id', auth()->user()->workspace_id)->get();
            }

            $templates_data = [];
            $i = 0;
            foreach ($templates as $t) {
                $templates_data[$i] = $t;
                $templates_data[$i]['start_time_am_pm'] = $this->AM_PM($t->start_time);
                $templates_data[$i]['end_time_am_pm'] = $this->AM_PM($t->end_time);
                $i++;
            }
            $data =  [
                'saved_templates' => $templates_data,
                'date' => $request->date,
            ];
        } else {
            $template = RosterTemplate::where('id', $request->template_id)->where('status', 1)->first();
            $data =  [
                'user_id' => $request->user_id,
                'date' => $request->date,
                'template' => $template
            ];
        }
        return $this->success($data, 'Get Data Successfully');
    }

    function AM_PM($TIME)
    {
        $time = Carbon::parse($TIME);
        $time = str_replace("M", "", $time->format('g:i A'));
        $time = str_replace(' ', '', $time);
        $time = str_replace(':00', '', $time);
        return $time;
    }

    function templateAssign(Request $request)
    {
        return $this->rosterTemplateAssign($request);
    }
    private function isOverlap($start1, $end1, $start2, $end2)
    {
        // Normalize the intervals by checking if they cross midnight
        if ($start1 > $end1) {
            $end1 = date('H:i:s', strtotime($end1) + 86400); // Add 24 hours to end1
        }
        if ($start2 > $end2) {
            $end2 = date('H:i:s', strtotime($end2) + 86400); // Add 24 hours to end2
        }

        return $start1 < $end2 && $start2 < $end1;
    }

    public function store(Request $request)
    {
        return $this->handleRosterTemplate($request);
    }


    public function publish(Request $request)
    {
        $start_date = $request->start_date < date('Y-m-d') ? date('Y-m-d') : $request->start_date;

        // Handle both emp_arr and recipients formats
        $employees = $request->emp_arr ?? $request->recipients ?? null;

        $this->publish_notify($start_date, $request->end_date, $request->note, $employees);

        return response()->json([
            'message' => 'Publish Successfully'
        ], 200);
    }

    public function publish_notify($start_date, $end_date, $note, $emp_arr)
    {
        $userTable = $this->getUserTable();
        $auth_id = 0;
        $workspace_id = 0;

        try {
            if ($userTable === "customer") {
                $auth_id = Auth::user()->id;
                $workspace_id = Auth::user()->current_workspace_id;
                $authPersonalDetails = User::find($auth_id);
            } elseif ($userTable === "emp") {
                $auth_id = Auth::user()->customer_id;
                $workspace_id = Auth::user()->workspace_id;
                $authPersonalDetails = EmpPersonalDetails::where('emp_id', Auth::user()->id)->first();
            }

            $dates_array = $this->getDatesBetween($start_date, $end_date);

            $roster_assigns = RosterAssign::whereIn('schedule_date', $dates_array)
                ->where('customer_id', $auth_id)
                ->where('workspace_id', $workspace_id)
                ->pluck('assign_to')
                ->unique()
                ->toArray();

            if ($emp_arr) {
                $roster_assigns = $emp_arr;
            }

            foreach ($roster_assigns as $roster_assign) {
                try {
                    $emp_company_details = EmpCompanyDetails::with('empPersonalDetails')->find($roster_assign);

                    if (
                        !$emp_company_details ||
                        !$emp_company_details->employee_email ||
                        !$emp_company_details->empPersonalDetails
                    ) {
                        Log::warning("Skipped employee ID {$roster_assign} — incomplete data.");
                        continue;
                    }

                    $fullName = trim(
                        $emp_company_details->empPersonalDetails->first_name . ' ' .
                            $emp_company_details->empPersonalDetails->middle_name . ' ' .
                            $emp_company_details->empPersonalDetails->last_name
                    );

                    $emailHtml = view('Emails/roster_notification', [
                        'email' => $emp_company_details->employee_email,
                        'name' => $fullName,
                        'note' => $note,
                        'subject' => 'Roster Scheduler Notification'
                    ])->render();

                    $params = [
                        'subject' => 'Roster Scheduler Notification | ' . env("APP_NAME"),
                        'to' => $emp_company_details->employee_email,
                        'msg' => $emailHtml
                    ];

                    dispatch(new SendEmailJob($params));
                    Log::info("Queued email for employee ID {$roster_assign} to {$emp_company_details->employee_email}");

                    $this->save_notifications(
                        'Roster Scheduler Notification',
                        'Shift Assigned To You',
                        Auth::user()->id,
                        $roster_assign,
                        'publish_roster_notification',
                        $emp_company_details->customer_id,
                        $emp_company_details->workspace_id
                    );
                } catch (\Exception $e) {
                    Log::error("Failed to process employee ID {$roster_assign}: " . $e->getMessage());
                }
            }
        } catch (\Exception $e) {
            Log::critical("publish_notify failed: " . $e->getMessage());
            return false;
        }

        return true;
    }
    public function publishCustom(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'recipients' => 'required',
            'start_date' => 'required',
            'end_date' => 'required',
            'note' => 'required'
        ]);

        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        } else {

            if (strtotime($request->end_date) < strtotime($request->start_date)) {
                return $this->message('End date must be bigger or equal to start date.', 400);
            }
            $items = $request->recipients;
            $emp_arr = [];
            $userTable = $this->getUserTable();
            $auth_id = 0;
            $workspace_id = 0;
            if ($userTable === "customer") {
                $auth_id = Auth::user()->id;
                $workspace_id = Auth::user()->current_workspace_id;
                $authPersonalDetails = User::where('id', Auth::user()->id)->first();
            }
            if ($userTable === "emp") {
                $auth_id = auth()->user()->customer_id;
                $workspace_id = auth()->user()->workspace_id;
                $authPersonalDetails = EmpPersonalDetails::where('emp_id', Auth::user()->id)->first();
            }
            if (in_array("all",  $items)) {
                $EmpCompanyDetails = EmpCompanyDetails::where(['del' => '0', 'compeleted' => '1', 'approved' => '1', 'status' => '1', 'customer_id' => $auth_id, 'workspace_id' => $workspace_id])->select('id')->get();
                foreach ($EmpCompanyDetails as $EmpCompanyDetail) {
                    if ($EmpCompanyDetail->id == 1) {
                        continue;
                    }
                    $emp_arr[] = $EmpCompanyDetail->id;
                }
            } else {
                foreach ($items as $item) {
                    $arr =  explode(".", $item);
                    if ($arr['0'] == 'employee') {
                        $EmpCompanyDetails = EmpCompanyDetails::where(['del' => '0', 'compeleted' => '1', 'approved' => '1', 'status' => '1', 'id' => $arr[1], 'customer_id' => $auth_id, 'workspace_id' => $workspace_id])->select('id')->get();
                        foreach ($EmpCompanyDetails as $EmpCompanyDetail) {
                            if ($EmpCompanyDetail->id == 1) {
                                continue;
                            }

                            $emp_arr[] = $EmpCompanyDetail->id;
                        }
                    }
                }
            }
            $emp_arr = array_unique($emp_arr);
            $this->publish_notify($request->start_date, $request->end_date, $request->note, $emp_arr); // this is skip for stop to send mail using microsoft
            return $this->message('Publish Successfully.', 200);
        }
    }

    public function publish_specific_person($emp_id)
    {
        $emp_company_details = EmpCompanyDetails::with('empPersonalDetails')->where('id', $emp_id)->first();

        if (!$emp_company_details) {
            return false;
        }

        if (!$emp_company_details->employee_email) {
            return false;
        }

        if (!$emp_company_details->empPersonalDetails) {
            return false;
        }

        $fullName = $emp_company_details->empPersonalDetails->first_name . ' ' .
            $emp_company_details->empPersonalDetails->middle_name . ' ' .
            $emp_company_details->empPersonalDetails->last_name;

        // Render the new email template
        $emailHtml = view('Emails/roster_notification', [
            'email' => $emp_company_details->employee_email,
            'name' => $fullName,
            'note' => '',
            'subject' => 'Roster Scheduler Notification'
        ])->render();

        // Use the job queue for email sending
        $params = [
            'subject' => 'Roster Scheduler Notification | ' . env("APP_NAME"),
            'to' => $emp_company_details->employee_email,
            'msg' => $emailHtml
        ];

        dispatch(new SendEmailJob($params));
        $this->save_notifications('Roster Scheduler Notification', 'Shift Assigned To You', Auth::user()->id, $emp_id, 'publish_roster_notification', $emp_company_details->customer_id, $emp_company_details->workspace_id);

        return true;
    }

    public function show(RosterTemplate $rosterTemplate)
    {
        //
    }

    public function edit(RosterTemplate $rosterTemplate)
    {
        //
    }

    public function repeatShiftUpdate(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'user_id' => 'required',
            'date' => 'required',
            'template_id' => 'required',
            'publish' => 'required',
            'start_time' => 'required',
            'end_time' => 'required',
            'break_minutes' => 'required',
            'color_code' => 'required',
            'shift_notes' => 'required',
            'repeat_shift' => 'required',
            'repeat_every' => 'required',
            'end_date' => 'required',
            'save_shift' => 'required',
            'edit' => 'nullable',
            'publish' => 'required'
        ]);





        if ($validator->fails()) {

            $errors = $validator->errors()->first();

            return response()->json([
                'message' => $errors
            ], 422);
        } else {

            $validatedData =  $validator->validated();

            $start_ = Carbon::parse($request->start_time);
            $end_ = Carbon::parse($request->end_time);
            $required_minutes =  $end_->diffInMinutes($start_);
            $required_minutes = $required_minutes - $request->break_minutes ?? 0;



            if ($request->date < date('Y-m-d')) {
                return response()->json([
                    'message' => 'Scheduler does not allow changes to be made for past dates.'
                ], 422);
            }

            if ($request->end_date < $request->date) {
                return response()->json([
                    'message' => 'End Date must be bigger than or Equal to ' . date('d-m-Y', strtotime($request->date)) . ' date.'
                ], 422);
            }

            $todays_date  = date('Y-m-d');

            if ($request->save_shift == '1') {
                RosterTemplate::insertGetId([
                    'start_time' => $request->start_time,
                    'end_time' => $request->end_time,
                    'break_minutes' => $request->break_minutes,
                    'color_code' => $request->color_code,
                    'shift_notes' => $request->shift_notes ?? null,
                    'repeat_shift' => '0',
                    'repeat_every' => $request->repeat_shift == '1' ?  $request->repeat_every : '',
                    'end_date' => $request->end_date,
                    'is_saved' => $request->save_shift,
                    'working_hours' => $required_minutes,
                    'created_by' =>  Auth::user()->id
                ]);
            }

            $insert_id =   RosterTemplate::insertGetId([
                'start_time' => $request->start_time,
                'end_time' => $request->end_time,
                'break_minutes' => $request->break_minutes,
                'color_code' => $request->color_code,
                'shift_notes' => $request->shift_notes ?? null,
                'repeat_shift' => $request->repeat_shift,
                'repeat_every' => $request->repeat_shift == '1' ?  $request->repeat_every : '',
                'end_date' => $request->end_date,
                'working_hours' => $required_minutes,
                'is_saved' => '0',
                'created_by' =>  Auth::user()->id
            ]);


            // $getDates = RosterAssign::where([

            //     ['assign_to', '=', $request->user_id],
            //     ['roster_template_id', '=', $request->template_id],
            //     ['schedule_date', '>=', $todays_date]

            // ])->get();




            RosterAssign::where([

                ['assign_to', '=', $request->user_id],
                ['roster_template_id', '=', $request->template_id],
                ['schedule_date', '>=', $request->date]

            ])->delete();




            $getDatesBetweens = $this->getDatesBetween($request->date, $request->end_date);
            $header_date =  Carbon::parse($request->date);


            foreach ($getDatesBetweens as $key => $getDatesBetween) {
                $getDatesBetween =  Carbon::parse($getDatesBetween);


                if ($request->repeat_every == '2') {
                    if ($header_date->format('D') == $getDatesBetween->format('D') && $key % 2 == 0) {
                        RosterAssign::insertGetId([
                            'assign_to' => $request->user_id,
                            'roster_template_id' =>  $insert_id,
                            'schedule_date' => $getDatesBetween,
                        ]);

                        $authPersonalDetails = EmpPersonalDetails::where('emp_id', Auth::user()->id)->first();

                        $empPersonalDetails  = EmpPersonalDetails::where('emp_id', $request->user_id)->first();

                        $history_arr = [
                            'description' => "<a href='" . url('/') . "/user-profile/" . Auth::user()->id . "' style='text-transform: capitalize;' role='button' class='primary text-decoration-none'> {$authPersonalDetails->first_name} {$authPersonalDetails->middle_name} {$authPersonalDetails->last_name}</a> assigned  shift '{$insert_id}' template to '{$empPersonalDetails->first_name} {$empPersonalDetails->middle_name} {$empPersonalDetails->last_name}'  at '" . date('d-m-Y', strtotime($getDatesBetween)) . "' date .",
                            'roster_template_id' => $insert_id
                        ];

                        $this->storeHistory($history_arr);
                    }
                } else {
                    if ($header_date->format('D') == $getDatesBetween->format('D')) {
                        RosterAssign::insertGetId([
                            'assign_to' => $request->user_id,
                            'roster_template_id' =>  $insert_id,
                            'schedule_date' => $getDatesBetween,
                        ]);

                        $authPersonalDetails = EmpPersonalDetails::where('emp_id', Auth::user()->id)->first();

                        $empPersonalDetails  = EmpPersonalDetails::where('emp_id', $request->user_id)->first();

                        $history_arr = [
                            'description' => "<a href='" . url('/') . "/user-profile/" . Auth::user()->id . "' style='text-transform: capitalize;' role='button' class='primary text-decoration-none'> {$authPersonalDetails->first_name} {$authPersonalDetails->middle_name} {$authPersonalDetails->last_name}</a> updated  shift '{$insert_id}' template to '{$empPersonalDetails->first_name} {$empPersonalDetails->middle_name} {$empPersonalDetails->last_name}'  at '" . date('d-m-Y', strtotime($getDatesBetween)) . "' date .",
                            'roster_template_id' => $insert_id
                        ];

                        $this->storeHistory($history_arr);
                    }
                }
            }

            return response()->json([
                'message' => 'Shift Updated Successfully'
            ], 200);
        }
    }

    public function destroy(Request $request)
    {
        if (date('Y-m-d', strtotime($request->date)) < date('Y-m-d')) {
            return $this->message('Scheduler does not allow changes to be made for past dates.', 422);
        }
        $userTable = $this->getUserTable();
        $auth_id = 0;
        $workspace_id = 0;
        if ($userTable === "customer") {
            $auth_id = Auth::user()->id;
            $workspace_id = Auth::user()->current_workspace_id;
            $authPersonalDetails = User::where('id', Auth::user()->id)->first();
        }
        if ($userTable === "emp") {
            $auth_id = auth()->user()->customer_id;
            $workspace_id = auth()->user()->workspace_id;
            $authPersonalDetails = EmpPersonalDetails::where('emp_id', Auth::user()->id)->first();
        }

        $name = !empty($authPersonalDetails->name) ? $authPersonalDetails->name : $authPersonalDetails->full_name;

        $RosterTemplate =   RosterTemplate::find($request->template_id);
        if (!$RosterTemplate) {
            return $this->message("Roster not found", 403);
        }

        if ($RosterTemplate->customer_id != $auth_id) {
            return $this->message("Don't have access", 403);
        }

        // Build query to find the roster assign record
        $query = RosterAssign::where([
            ['assign_to', '=', $request->user_id],
            ['roster_template_id', '=', $request->template_id],
            ['schedule_date', '=', $request->date],
            ['site_id', '=', $request->site_id],
            ['project_id', '=', $request->project_id],
        ]);

        // First, get the roster assign record to check site_id and project_id
        $rosterAssign = $query->first();

        if (!$rosterAssign) {
            return $this->message("No Record Exist", 404);
        }


        // Delete the roster assign
        $assigne = $rosterAssign->delete();
        if (!$assigne) {
            return $this->message("No Record Exist", 404);
        }
        $this->singleRosterTemplateDelete($request->template_id);
        $empPersonalDetails  = EmpPersonalDetails::where('emp_id', $request->user_id)->first();
        if ($userTable === "customer") {
            $history_arr = [
                'description' => "<a href='" . url('/') . "/user-profile/" . Auth::user()->id . "' style='text-transform: capitalize;' role='button' class='primary text-decoration-none'> {$authPersonalDetails->name} </a> deleted a shifts which was assigned  '{$request->template_id}' template to '{$empPersonalDetails->first_name} {$empPersonalDetails->middle_name} {$empPersonalDetails->last_name}'  at '" . date('d-m-Y', strtotime($request->date)) . "' date .",
                'roster_template_id' => $request->template_id
            ];
        }
        if ($userTable === "emp") {
            $history_arr = [
                'description' => "<a href='" . url('/') . "/user-profile/" . Auth::user()->id . "' style='text-transform: capitalize;' role='button' class='primary text-decoration-none'> {$authPersonalDetails->first_name} </a> deleted a shifts which was assigned  '{$request->template_id}' template to '{$empPersonalDetails->first_name} {$empPersonalDetails->middle_name} {$empPersonalDetails->last_name}'  at '" . date('d-m-Y', strtotime($request->date)) . "' date .",
                'roster_template_id' => $request->template_id
            ];
        }
        $this->storeHistory($history_arr);
        return $this->message("Roster Assignee Deleted Successfully", 200);
    }

    public function rosterTemplateDelete($templateId)
    {

        $rosterTemplate  = RosterTemplate::where('id', $templateId)->first();

        if (!$rosterTemplate) {
            return response()->json([
                'message' => 'Roster Template not found.'
            ], 404);
        }
        if ($rosterTemplate->is_saved != 1) {
            $rosterAssignee = RosterAssign::where('roster_template_id', $templateId)->exists();
            if (!$rosterAssignee) {
                $data = RosterTemplate::where('id', $templateId)->delete();
                return response()->json([
                    'message' => 'Template Deleted Successfully.' . $rosterTemplate
                ], 200);
            }
        }
    }

    public function singleRosterTemplateDelete($templateId)
    {
        $rosterTemplate  = RosterTemplate::where('id', $templateId)->first();
        if ($rosterTemplate->is_saved != 1) {
            $rosterAssignee = RosterAssign::where('roster_template_id', $templateId)->count();
            if ($rosterAssignee == 0) {
                $data = RosterTemplate::where('id', $templateId)->delete();
                return response()->json([
                    'message' => 'Template Deleted Successfully.' . $rosterTemplate
                ], 200);
            }
        }
    }
    function getDatesBetween($start_date, $end_date)
    {
        $dates = [];
        $start = Carbon::parse($start_date);
        $end = Carbon::parse($end_date);
        while ($start->lte($end)) {
            $dates[] = $start->toDateString();
            $start->addDay();
        }
        return $dates;
    }

    /**
     * Generate dates with proper day names for frontend mapping
     */
    function generateDatesWithDayNames($dates_array, $scheduler_mode)
    {
        $dates_with_info = [];
        foreach ($dates_array as $index => $date) {
            $carbonDate = Carbon::parse($date);
            $dayName = strtoupper($carbonDate->format('l')); // MONDAY, TUESDAY, etc.
            $dayNumber = $carbonDate->day;
            $dayOfWeek = $carbonDate->dayOfWeek; // 0 = Sunday, 1 = Monday, etc.   
            $dates_with_info[] = [
                'date' => $date,
                'day_name' => $dayName,
                'day_number' => $dayNumber,
                'day_of_week' => $dayOfWeek,
                'is_weekend' => in_array($dayOfWeek, [0, 6]), // Sunday and Saturday
                'formatted_date' => $carbonDate->format('Y-m-d'),
                'display_date' => $carbonDate->format('M d'),
            ];
        }
        return $dates_with_info;
    }

    public function getHistory()
    {

        $userTable = $this->getUserTable();
        if ($userTable === "customer") {
            $auth_id = Auth::user()->id;
            $workspace_id = Auth::user()->current_workspace_id;
        }
        if ($userTable === "emp") {
            $auth_id = auth()->user()->customer_id;
            $workspace_id = auth()->user()->workspace_id;
        }
        $history = RosterHistory::orderBy('id', 'DESC')->where('customer_id', $auth_id)->where('workspace_id', $workspace_id)->get();

        // Remove anchor tags from description while preserving the text content
        $history->transform(function ($item) {
            if (isset($item->description)) {
                // Remove anchor tags and keep only the text content
                $item->description = strip_tags($item->description);
            }
            return $item;
        });

        $data['history'] = $history;
        return $this->success($history, 'Get History Successfully');
    }


    public function storeHistory($arr)
    {
        $userTable = $this->getUserTable();
        if ($userTable === "customer") {
            $auth_id = Auth::user()->id;
            $workspace_id = Auth::user()->current_workspace_id;
        }
        if ($userTable === "emp") {
            $auth_id = auth()->user()->customer_id;
            $workspace_id = auth()->user()->workspace_id;
        }
        RosterHistory::create([
            'roster_template_id' => $arr['roster_template_id'],
            'updated_by' => Auth::user()->id,
            'description' => $arr['description'],
            'customer_id' =>  $auth_id,
            'workspace_id' =>  $workspace_id,
        ]);
    }


    public function rosterApi(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'emp_id' => 'required',
            'date' => 'required'
        ]);

        if ($validator->fails()) {

            $error = $validator->errors()->first();

            return response()->json([
                'message' => $error
            ], 422);
        } else {

            $validatedData =  $validator->validated();
            $RosterAssigns = RosterAssign::with('rosterTemplate')->where(['assign_to' => $validatedData['emp_id'], 'schedule_date' => $validatedData['date']])->get();

            $data['roster'] =  $RosterAssigns;

            return response()->json([
                'message' => 'Get Roster Successfully',
                'data' => $data
            ], 200);
        }
    }



    public function bulkScheduleSave(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'start_date' => 'required',
            'end_date' => 'required|after_or_equal:start_date',
            'start_time' => 'required',
            'end_time' => 'required|after:start_time',
            'color_code' => 'required',
            'break_minutes' => 'nullable|integer|min:0',
            'shift_notes' => 'nullable',
            'working_days_hidden' => 'required',
            'working_hours' => 'required|min:1',
            'team_ids' => 'nullable|array',
            'external_ids' => 'nullable|array',
            'internal_ids' => 'nullable|array',
            'users_ids' => 'nullable|array',
            'site_id' => 'nullable|integer|exists:sites,id',
            'project_id' => 'nullable|integer|exists:projects,id'

        ], [
            'end_time.after' => 'End time must be after start time',
            'working_days_hidden.required' => 'Please select atleast one day',
            'working_hours.required' => 'Working hours is required',
            'working_hours.min' => 'Working hours must be greater than 0',
            'site_id.exists' => 'Selected site does not exist',
            'project_id.exists' => 'Selected project does not exist',
            'break_minutes.integer' => 'Break minutes must be an integer',
            'break_minutes.min' => 'Break minutes must be greater than 0',
        ]);
        // $validator = $this->customerSubscriptionRequestValidationRequest($request);
        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        } else {
            if (date('Y-m-d', strtotime($request->start_date)) < date('Y-m-d')) {
                return $this->message('Scheduler does not allow changes to be made for past dates.', 422);
            }

            // Merge team_ids, external_ids, and internal_ids into users_ids
            $mergedUserIds = $this->mergeUserIdsFromTeamsAndIndividuals($request);

            if (empty($mergedUserIds)) {
                return $this->message('No valid employees found from the selected teams and individuals.', 422);
            }


            $arr = [
                'start_date' => $request->start_date,
                'end_date' => $request->end_date,
                'start_time' => $request->start_time,
                'end_time' => $request->end_time,
                'color_code' => $request->color_code,
                'break_minutes' => $request->break_minutes ?? 0,
                'shift_notes' => $request->shift_notes ?? null,
                'users_ids' => $mergedUserIds,
                'working_hours' => $request->working_hours,
                'working_days_hidden' => $request->working_days_hidden,
                'site_id' => $request->site_id ?? null,
                'project_id' => $request->project_id ?? null
            ];

            return $this->bulkScheduleRoasterCreate($arr, $arr);
        }
    }


    private function mergeUserIdsFromTeamsAndIndividuals(Request $request)
    {
        $userTable = $this->getUserTable();
        $auth_id = 0;
        $workspace_id = 0;

        if ($userTable === "customer") {
            $auth_id = Auth::user()->id;
            $workspace_id = Auth::user()->current_workspace_id;
        }
        if ($userTable === "emp") {
            $auth_id = auth()->user()->customer_id;
            $workspace_id = auth()->user()->workspace_id;
        }

        $mergedUserIds = [];

        // Add internal IDs if provided
        if ($request->has('internal_ids') && is_array($request->internal_ids)) {
            $mergedUserIds = array_merge($mergedUserIds, $request->internal_ids);
        }

        // Add external IDs if provided
        if ($request->has('external_ids') && is_array($request->external_ids)) {
            $mergedUserIds = array_merge($mergedUserIds, $request->external_ids);
        }

        // Add team member IDs if team_ids provided
        if ($request->has('team_ids') && is_array($request->team_ids)) {
            $teamMemberIds = EmpTeamsMember::whereIn('team_id', $request->team_ids)
                ->where('del', '0')
                ->pluck('emp_id')
                ->toArray();

            $mergedUserIds = array_merge($mergedUserIds, $teamMemberIds);
        }

        // Remove duplicates and filter out invalid employees
        $mergedUserIds = array_unique($mergedUserIds);

        // Filter to only include valid employees for this customer/workspace
        $validEmployeeIds = EmpCompanyDetails::whereIn('id', $mergedUserIds)
            ->where('customer_id', $auth_id)
            ->where('workspace_id', $workspace_id)
            ->where('del', '0')
            ->where('compeleted', '1')
            ->where('approved', '1')
            ->where('status', '1')
            ->pluck('id')
            ->toArray();

        return $validEmployeeIds;
    }

    public function deleteTemplate(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'start_time' => 'required',
            'end_time' => 'required|after:start_time',
            'start_date' => 'required|after_or_equal:today',
            'end_date' => 'required|after_or_equal:start_date',
            'users_ids' => ['required', 'array', 'min:1'],
        ], [
            'end_time.after' => 'End time must be after start time',
            'users_ids.required' => 'Please select atleast one employee',
        ]);
        if ($validator->fails()) {

            $errors = $validator->errors()->first();
            return $this->handleValidationFailure($validator);
        }
        $roster_template_ids = RosterTemplate::join('roster_assigns', 'roster_templates.id', 'roster_assigns.roster_template_id')
            ->where('roster_templates.start_time', $request->start_time)->where('roster_templates.end_time', $request->end_time)
            ->where('roster_assigns.schedule_date', '<=', $request->end_date)
            ->where('roster_assigns.schedule_date', '>=', $request->start_date)
            ->whereIn('roster_assigns.assign_to', $request->users_ids)
            ->where('roster_assigns.site_id', $request->site_id)
            ->where('roster_assigns.project_id', $request->project_id)
            ->pluck('roster_assigns.id as template_assign_id')->toArray();

        if (empty($roster_template_ids)) {
            return $this->message('No roster found', 404);
        }
        $count = count($roster_template_ids);
        //  RosterAssign::whereIn('id',$roster_template_ids)->delete();
        foreach ($roster_template_ids as $template_assign_id) {
            $template = RosterAssign::where('id', $template_assign_id)->first();

            RosterAssign::where('id', $template_assign_id)->delete();

            if ($template) {
                $this->rosterTemplateDelete($template->roster_template_id); // Testing is remaing data is passing template instead of assignee 
            }
        }
        return $this->message('Roster deleted successfully.', 200);
    }

    /**
     * Bulk edit roster schedules
     * This method deletes existing rosters and then creates new ones based on the provided payload
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function bulkScheduleUpdate(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'start_date' => 'required',
            'end_date' => 'required|after_or_equal:start_date',
            'start_time' => 'required',
            'end_time' => 'required|after:start_time',
            'color_code' => 'required',
            'break_minutes' => 'nullable|integer|min:0',
            'shift_notes' => 'nullable',
            'working_days_hidden' => 'required',
            'working_hours' => 'required|min:1',
            'team_ids' => 'nullable|array',
            'external_ids' => 'nullable|array',
            'internal_ids' => 'nullable|array',
            'users_ids' => 'nullable|array',
            'site_id' => 'nullable|integer|exists:sites,id'
        ], [
            'end_time.after' => 'End time must be after start time',
            'working_days_hidden.required' => 'Please select atleast one day',
            'working_hours.required' => 'Working hours is required',
            'working_hours.min' => 'Working hours must be greater than 0',
            'site_id.exists' => 'Selected site does not exist',
            'break_minutes.integer' => 'Break minutes must be an integer',
            'break_minutes.min' => 'Break minutes must be greater than 0'
        ]);

        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        }

        if (date('Y-m-d', strtotime($request->start_date)) < date('Y-m-d')) {
            return $this->message('Scheduler does not allow changes to be made for past dates.', 422);
        }

        // Merge team_ids, external_ids, and internal_ids into users_ids
        $mergedUserIds = $this->mergeUserIdsFromTeamsAndIndividuals($request);

        if (empty($mergedUserIds)) {
            return $this->message('No valid employees found from the selected teams and individuals.', 422);
        }

        $userTable = $this->getUserTable();
        $auth_id = 0;
        $workspace_id = 0;

        if ($userTable === "customer") {
            $auth_id = Auth::user()->id;
            $workspace_id = Auth::user()->current_workspace_id;
        }
        if ($userTable === "emp") {
            $auth_id = auth()->user()->customer_id;
            $workspace_id = auth()->user()->workspace_id;
        }

        // Step 1: Delete existing rosters for the given date range and users
        // Only delete rosters for the days that match working_days_hidden
        $days_array = explode(",", $request->working_days_hidden);
        $getDatesBetweens = $this->getDatesBetween($request->start_date, $request->end_date);

        // Filter dates to only include working days
        $working_dates = [];
        foreach ($getDatesBetweens as $date) {
            if (in_array(Carbon::parse($date)->format('D'), $days_array)) {
                $working_dates[] = $date;
            }
        }

        // Get all roster assign IDs that match the criteria (only for working days)
        $roster_assign_ids = RosterAssign::whereIn('schedule_date', $working_dates)
            ->whereIn('assign_to', $mergedUserIds)
            ->where('customer_id', $auth_id)
            ->where('workspace_id', $workspace_id)
            ->pluck('id')
            ->toArray();

        // Delete roster assigns and clean up unused templates
        if (!empty($roster_assign_ids)) {
            foreach ($roster_assign_ids as $assign_id) {
                $template = RosterAssign::where('id', $assign_id)->first();

                if ($template) {
                    RosterAssign::where('id', $assign_id)->delete();
                    $this->rosterTemplateDelete($template->roster_template_id);
                }
            }
        }

        // Step 2: Create new rosters using the same logic as bulkScheduleSave
        $arr = [
            'start_date' => $request->start_date,
            'end_date' => $request->end_date,
            'start_time' => $request->start_time,
            'end_time' => $request->end_time,
            'color_code' => $request->color_code,
            'break_minutes' => $request->break_minutes ?? 0,
            'shift_notes' => $request->shift_notes ?? null,
            'users_ids' => $mergedUserIds,
            'working_hours' => $request->working_hours,
            'working_days_hidden' => $request->working_days_hidden,
            'site_id' => $request->site_id ?? null
        ];

        return $this->bulkScheduleRoasterCreate($arr, $arr);
    }



    public function templateDelete(Request $request)
    {

        $validator = Validator::make(
            $request->all(),
            [
                "template_id" => "required|exists:roster_templates,id",
            ],
            [
                "template_id.exists" => "Template not found",
            ]
        );

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

        $templateId = $request->input('template_id');

        // Find the template along with its related assigns
        $roster_template = RosterTemplate::with(['assigns' => function ($query) {
            $query->where('schedule_date', '>=', now()->toDateString()); // Filtering to include only today's and future assigns
        }])
            ->find($templateId);

        if ($roster_template) {
            // Delete all the filtered related assigns (roster_assigns)
            foreach ($roster_template->assigns as $assign) {
                $assign->delete(); // Delete each filtered assign
            }

            // Check if all assigns are deleted or only the filtered ones
            if ($roster_template->assigns()->exists()) {
                $roster_template->update(['status' => 0]);
                return response()->json(['success' => 'Only future and todays assignments deleted']);
            } else {
                // Now delete the template itself if no assigns are left
                $roster_template->delete();
                return response()->json(['success' => 'Template and its assignments deleted successfully']);
            }
        } else {
            return response()->json(['error' => 'Template not found'], 404);
        }
    }
    public function rosterDataCleanApi($id)
    {
        $roster_template_ids =  RosterTemplate::find($id);
        // this code get same roster according to Start Time , End Time and Color Code 
        $getSameRoster = RosterTemplate::where('start_time', $roster_template_ids->start_time)
            ->where('end_time', $roster_template_ids->end_time)
            ->where('color_code', $roster_template_ids->color_code)
            // ->where('end_date',$roster_template_ids->end_date)  //this end time is seprate confirm end time is nessary or not 
            ->pluck("id")
            ->toArray();
        // Important aslo discusss Date start-date and End-date
        // this count to confim entry in Roster Template and Assigne Template   
        return   $getSameRoster;
        $totaleRosterCount = count($getSameRoster);
        // this code get Assignee roster according to  the list $getSameRoster roaster where start Time, End Time and Color Code
        $assigneRoster = RosterAssign::whereIn('roster_template_id', $getSameRoster)->get();
        // this count to confim entry in Roster Template and Assigne Template            
        $totaleAssigneRoster = count($assigneRoster);
        // update roster_template_id to passing roaster id on params
        $assigneRoster = RosterAssign::whereIn('roster_template_id', $getSameRoster)
            ->update(['roster_template_id' => $id]);



        // Filter array to remove 
        $sameRosterRemove = array_values(array_filter($getSameRoster, function ($value) use ($id) {
            return intval($value) !== intval($id);
        }));

        // delete  repated  data 
        $assigneRoster = RosterTemplate::whereIn('id', $sameRosterRemove)->delete();



        return $assigneRoster;
    }
    // This is not done yet  i calculata this  and testing is remaing  
    public function rosterDataCleanApiloop($limit, $badge)
    {
        // Calculate the start and end IDs based on the limit and badge.
        $startId = ($badge - 1) * $limit + 1;
        $endId = $badge * $limit;
        // Initialize a counter for the total deleted roster templates.
        $totalDeleted = 0;

        // Loop through the range of IDs.
        for ($id = $startId; $id <= $endId; $id++) {
            // Step 1: Retrieve the roster template based on the current ID.
            $roster_template_ids = RosterTemplate::find($id);

            if (!$roster_template_ids) {
                continue; // Skip if the roster template doesn't exist.
            }

            // Step 2: Find all roster templates with the same start time, end time, and color code as the current one.
            $getSameRoster = RosterTemplate::where('start_time', $roster_template_ids->start_time)
                ->where('end_time', $roster_template_ids->end_time)
                ->where('color_code', $roster_template_ids->color_code)
                // ->where('end_date',$roster_template_ids->end_date)  //this end time is seprate confirm end time is nessary or not  also check on live and ensure  
                ->pluck("id")
                ->toArray();

            // Step 3: Count the number of matching roster templates.
            $totaleRosterCount = count($getSameRoster);

            // // Step 4: Find all `RosterAssign` entries that reference the matching roster templates. (for testing and checking )
            // $assigneRoster = RosterAssign::whereIn('roster_template_id', $getSameRoster)->get();

            // Step 5: Update the `roster_template_id` in `RosterAssign` entries to the current template ID (`$id`).
            $assigneRoster = RosterAssign::whereIn('roster_template_id', $getSameRoster)
                ->update(['roster_template_id' => $id]);

            // Step 6: Filter out the current template ID (`$id`) from the list of matching roster template IDs.
            $sameRosterRemove = array_values(array_filter($getSameRoster, function ($value) use ($id) {
                return intval($value) !== intval($id);
            }));

            // Step 7: Delete the remaining duplicate roster templates.
            $deleted =  RosterTemplate::whereIn('id', $sameRosterRemove)->where('is_saved', '!=', 1)->delete();
            $totalDeleted += $deleted;
        }

        // Optionally, you can return a message or the number of cleaned records.
        return response()->json([
            'message' => "Roster data cleaned for ID range $startId to $endId.",
            'total_deleted' => $totalDeleted
        ]);
    }
}
