<?php

namespace App\Http\Controllers\Api\Hrms;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

use App\Models\Hrms\Attendance;
use App\Models\Hrms\Employee;
use App\Models\Hrms\ShiftMaster;
use App\Models\Hrms\AssingShift;
use App\Models\Hrms\Holiday;
use App\Models\User;
use Validator;
use Auth;

class AttendanceController extends Controller
{

    public function attendanceCreateUpdate(Request $request){

        $auth=Auth::user();

        $validator=validator($request->all(),[
            'user_id'=>'required',
            'date'=>'required',
            'punch_in'=>'required',
            'punch_out'=>'required',
        ]);

        if ($validator->fails()) { 
            return [
                'success' => false, 
                'message' => $validator->errors()->first(),
            ];

        } else {

            try{

                $data=[
                    'user_id','date','punch_in','punch_out','shift_id','shift_name',
                    'total_hours_worked','reason','overtime','status','user_name'
                ];
                
                foreach ($data as $key => $value) {
                    if(isset($request[$value]) && $request[$value]!=null && $request[$value]!=''){
                        $obj[$value]=$request[$value];
                    }
                }

                $punchInTime = new \DateTime($request['punch_in']);
                $punchOutTime = new \DateTime($request['punch_out']);
                
                // Check if punch-out time is earlier than punch-in time
                if ($punchOutTime < $punchInTime) {
                    $punchOutTime->modify('+1 day');  // Add 1 day to punch-out time
                }
                
                $interval = $punchInTime->diff($punchOutTime);
                $total_hours_worked = $interval->format('%h Hrs and %i min');
                $obj['total_hours_worked'] = $total_hours_worked;
                
                $shiftMaster=ShiftMaster::findOrFail($request['shift_id']);;

                 if (!$shiftMaster) {
                    return response()->json(['error' => true, 'message' => 'Shift not found'], 404);
                }

                $endtime = new \DateTime($shiftMaster->end_time);
                $punchOutTime = new \DateTime($request['punch_out']);
                
                if ($punchOutTime > $endtime) {
                    // Calculate overtime
                    $interval = $endtime->diff($punchOutTime);
                    $total_overtime_worked = $interval->format('%h Hrs and %i min');
                } else {
                    // No overtime
                    $total_overtime_worked = "0 Hrs and 0 min";
                }
                
                $obj['overtime'] = $total_overtime_worked;
                
                                
                if($request->id>0){

                    try{

                        $attendance=Attendance::findOrFail($request['id']);
                        $attendance->update($obj);

                    } catch (\Exception $e) {
                        return response(['error' => true, 'message' => 'Invalid Id to update'], 404); 
                    }
                }else{
                
                    $checkAttendance = Attendance::where('user_id', $request['user_id'])
                    ->where('date',$request['date'])->where('is_disabled', '0')
                    ->where('organisation_id', $auth['active_organisation'])
                    ->first();

                    if ($checkAttendance != null) {
                        $response = [
                            'message' => "Attendance already exist",
                            'success' => false,
                            'vendor' => $checkAttendance,
                        ];

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

                    $attendance=Attendance::create($obj);
                    // Log::info($attendance);
                }

                return response()->json([
                    'status'=>200,
                    'message'=> $request->id>0 ? 'Attendance update successfully':'Attendance Created Successfully',
                    'result'=>$attendance
                ],200);
                
            } catch (\Exception $e) {
                return response(['error' => true, 'message' => $e->getMessage()], 404); 
            }
        }
    }

    public function getAttendance(Request $request)
    {
        $user = Auth::user();
        $todayDate = date('d-m-Y'); 
    
        $today_present = 0;
        $today_absent = 0;
        $today_halfday = 0;
    
        if ($user != null) {
            $attendanceList = Attendance::where('is_disabled', '0')
                ->with('employee','enteredby')
                ->where('organisation_id', $user['active_organisation']);
    
            // Search filter
            if (isset($request['search']) && $request['search'] != '') {
                $keyword = "%" . $request['search'] . "%";
                $attendanceList = $attendanceList->whereRaw(
                    "(shift_name LIKE ? OR date LIKE ? OR user_name LIKE ?)",
                    [$keyword, $keyword, $keyword]
                );
            }
    
            // Status filter
            if ($request['status'] != '' && isset($request['status'])) {
                $attendanceList = $attendanceList->where('status', $request['status']);
            }
    
            // Filter by custom date
            if ($request['custom_date'] != '' && isset($request['custom_date'])) {
                $customDate = $request->custom_date;
    
                $attendanceList = $attendanceList->where('date', $customDate);
    
                $today_present = (clone $attendanceList)->where('status', '0')->count();
                $today_absent = (clone $attendanceList)->where('status', '1')->count();
                $today_halfday = (clone $attendanceList)->where('status', '2')->count();
            }
    
            // Filter by date range (fromDate and toDate)
            if ($request['fromDate'] != '' && isset($request['toDate'])) {
                $fromDate = $request->fromDate;
                $toDate = $request->toDate . ' 23:59:59';
    
                $attendanceList = $attendanceList
                    ->where('date', '>=', $fromDate)
                    ->where('date', '<=', $toDate);
    
                $today_present = (clone $attendanceList)->where('status', '0')->count();
                $today_absent = (clone $attendanceList)->where('status', '1')->count();
                $today_halfday = (clone $attendanceList)->where('status', '2')->count();
            }
    
            // Default to today if no date filters are provided
            if (empty($request['custom_date']) && empty($request['fromDate']) && empty($request['toDate'])) {
                $attendanceList = $attendanceList->where('date', $todayDate);
                $today_present = (clone $attendanceList)->where('status', '0')->count();
                $today_absent = (clone $attendanceList)->where('status', '1')->count();
                $today_halfday = (clone $attendanceList)->where('status', '2')->count();
            }
    
            // Count total employees
            $total_emp = Employee::where('is_disabled', '0')
                ->where('organisation_id', $user['active_organisation'])
                ->count();
    
            // Sorting and pagination
            $sortOrder = ($request['sortOrder'] == 1) ? 'desc' : 'asc';
            $sortBy = $request['sortBy'] ?? 'id';

            $count=$attendanceList->count();
            $attendanceList = $attendanceList
                ->orderBy($sortBy, $sortOrder)
                ->skip(($request['currentpage'] - 1) * ($request['noofrec'] ?? 100))
                ->take($request['noofrec'] ?? 100)
                ->get();
    
            // Prepare response
            $response = [
                'result' => $attendanceList,
                'total_count' => $count,
                'total_employee' => $total_emp,
                'today_present' => $today_present,
                'today_absent' => $today_absent,
                'today_halfday' => $today_halfday,
                'message' => 'Successful',
            ];
        } else {
            $response = [
                'result' => [],
                'total_count' => 0,
                'total_employee' => 0,
                'today_present' => 0,
                'today_absent' => 0,
                'today_halfday' => 0,
                'message' => 'Invalid User',
            ];
        }
    
        return response()->json($response);
    }
    
    
    // Filter Users
    public function fetchuserbyquery($attendanceList,$request){

        if(isset($request['search']) && $request['search']!='') {
            $keyword = "%".$request['search']."%";
            $attendanceList = $attendanceList->whereRaw(" (shift_name like ? or date like ? or user_name like ?) ", array($keyword , $keyword , $keyword));
        }

        if($request['status']!='' && isset($request['status'])){
            $attendanceList=$attendanceList->where('status',$request['status']);
        }

        // get custom_date data by transaction_date
        if ($request['custom_date']!='' && isset($request['custom_date'])) {
            $customDate = $request->custom_date;
            $attendanceList = $attendanceList->whereDate('created_at', $customDate);
        }

        // get fromDate toDate data by created_at
        if ($request['fromDate']!='' && isset($request['toDate'])) {
            $fromDate = $request->fromDate;
            $toDate = $request->toDate;
            $toDate .= ($fromDate === $toDate) ? ' 23:59:59' : ' 23:59:59';
        
            // 'fromDate' and 'toDate'
            $attendanceList = $attendanceList->where('created_at', '>=', $fromDate)->where('created_at', '<=', $toDate);
        }

        return $attendanceList;
    }

    public function getAttendancedetails(Request $request) {
        $response = [];
        $auth = Auth::user();
        
        // Validate Input
        $validator = Validator::make($request->all(), [
            'id' => 'required'
        ]);
    
        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => $validator->errors()->first()
            ]);
        }
    
        $attendance = Attendance::where('id', $request->id)->with(['employee', 'employee.department', 'employee.designation','enteredby'])
                        ->where('organisation_id', $auth->active_organisation) 
                        ->first();
    
        if (!$attendance) {
            return response()->json([
                'success' => false,
                'message' => 'Attendance not found'
            ], 404);
        }
    
        $response = [
            'result' => $attendance,
            'success' => true,
            'message' => 'Attendance Details Retrieved Successfully.'
        ];
    
        return response()->json($response);
    }
    
    public function deleteAttendance(Request $request){

        $auth=Auth::user();

        $validator=validator($request->all(),[
           'id'=>'required|integer'
        ]);

       if ($validator->fails()) { 
           return [
               'success' => false, 
               'message' => $validator->errors()->first(),
           ];

       } else {

           try{
                $attendance = Attendance::where('id',$request->input('id'))
                            ->where('organisation_id',$auth['active_organisation'])
                            ->first();

                if (!$attendance) {
                    return response()->json([
                        'success' => false,
                        'message' => 'Attendance not found'
                    ], 404);
                }

                $attendance['is_disabled']='1';
                $attendance->update();

                $response=[
                    'success'=>true,
                    'message'=>'Attendance Deleted successfully.'
                ];

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

            } catch (\Exception $e) {
                return response(['error' => true, 'message' => $e->getMessage()], 404); 
            }
       }
    }

    public function updateStatusAttendance(Request $request){

        $auth=Auth::user();
        
        $validator=validator($request->all(),[
            'id'=>'required|integer'
         ]);
 
        if ($validator->fails()) { 
            return [
                'success' => false, 
                'message' => $validator->errors()->first(),
            ];
 
        } else {

            try{
                
                $attendance = Attendance::where('id',$request->input('id'))->first();
                $attendance['status']=$request['status'];
                $attendance->update();

                $response=[
                    'success'=>true,
                    'message'=>'Status Updated successfully.',
                    'result'=>$attendance
                ];

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

            } catch (\Exception $e) {
                return response(['error' => true, 'message' => $e->getMessage()], 404); 
            }
        }
    }

    public function getAttendanceSummary(Request $request)
    {
        $user = Auth::user();
        $todayDate = date('Y-m-d');
    
        if ($user != null) {
            // Default query to fetch attendance summary
            $attendanceSummaryQuery = Attendance::where('user_id', $request->user_id)
                ->where('is_disabled', '0')
                ->with('employee')
                ->where('organisation_id', $user['active_organisation']);
    
            // Filter by fiscal year (fy) if provided
            if (!empty($request->fy)) {
                $attendanceSummaryQuery = $attendanceSummaryQuery->whereYear('date', $request->fy);
            }
    
            // Filter by month if provided
            if (!empty($request->month)) {
                $month = date('m', strtotime($request->month)); // Convert month name to month number
                $attendanceSummaryQuery = $attendanceSummaryQuery->whereMonth('date', $month);
            }
    
            // Fetch holidays for the given organisation
            $holidays = Holiday::where('is_disabled', '0')
                ->where('organisation_id', $user['active_organisation'])
                ->get();
    
            // Apply pagination before fetching the results
            $attendanceSummary = $attendanceSummaryQuery->orderBy('id', 'desc')
                ->skip($request['noofrec'] * ($request['currentpage'] - 1))
                ->take($request['noofrec'] ?? 100)
                ->get();
    
            // Iterate over each attendance entry and check for matching holidays
            foreach ($attendanceSummary as $attendance) {
                $attendanceDate = $attendance->date;
    
                // Check if the attendance date matches any holiday range
                $matchingHoliday = $holidays->first(function ($holiday) use ($attendanceDate) {
                    return $attendanceDate >= $holiday->from_date && $attendanceDate <= $holiday->to_date;
                });
    
                // If a matching holiday is found, attach its name to the attendance record
                if ($matchingHoliday) {
                    $attendance->holiday_name = $matchingHoliday->holiday_name ?? 'Unnamed Holiday';
                } else {
                    $attendance->holiday_name = null; // No holiday on this date
                }
            }
    
            $response = [
                'attendanceSummary' => $attendanceSummary,
                'message' => 'Successful',
            ];
    
        } else {
            $response = [
                'attendanceSummary' => [],
                'message' => 'Invalid User',
            ];
        }
    
        return response()->json($response);
    }
    
    
    
}