<?php

namespace App\Modules\Hr\controllers\api\v1;

use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\BaseController;
use App\Modules\Hr\TimeLog;
use App\Modules\Hr\TimeLogChangeRequest;
use App\Models\User;
use Carbon\Carbon;

class TimeLogControllerREST extends BaseController
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        Log::info('TimeLogControllerRESTv1::index called');
        
        // Check to see if the last record has been requested
        if (request()->has('lastRecord') && request()->get('lastRecord') != 'false') {
            $lastRecord = TimeLog::lastRecord()->first();
            if ($lastRecord) {
                $recordData = $lastRecord->toArray();
                // Sanitize data to remove control characters
                array_walk_recursive($recordData, function(&$item) {
                    if (is_string($item)) {
                        $item = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $item);
                    }
                });
                return $recordData;
            }
            return Response::json([]);
        }

        // Check to see if the request is for user statuses
        if (request()->get('userStatuses') && request()->get('userStatuses') != 'false') {
            $users = User::getActiveList();
            $timeLogs = TimeLog::today()->groupBy('user_id')->orderBy('time', 'desc')->get();
            foreach ($users as $user) {
                $log = $timeLogs->first(function($item) use ($user) {
                    return $item->user_id == $user->id;
                });
                $user->latest_time_log = ($log) ? $log->toArray() : null;
            }

            // Sanitize data to remove control characters
            $usersArray = $users->toArray();
            array_walk_recursive($usersArray, function(&$item) {
                if (is_string($item)) {
                    $item = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $item);
                }
            });

            return [
                'data' => $usersArray,
            ];
        }

        // Retrieves all time logs grouped by month
        $query = TimeLog::with('pending_change_requests')->own()->period(request()->get('startDate'), request()->get('endDate'))->orderBy('time', 'asc');

        // Paginate the results
        $query = $query->paginate(request()->get('limit', 500));

        // Fetch the user's first record
        $first_record = TimeLog::where('user_id', request()->get('user_id', Auth::user()->id))->where('pending_change_request', 0)->firstRecord()->first();

        // Prepare the response
        $data = $query->getCollection()->toArray();

        // Sanitize data to remove control characters that cause JSON encoding errors
        array_walk_recursive($data, function(&$item) {
            if (is_string($item)) {
                // Remove control characters except newline and tab
                $item = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $item);
            }
        });

        $first_record_data = $first_record ? $first_record->toArray() : null;
        if ($first_record_data) {
            array_walk_recursive($first_record_data, function(&$item) {
                if (is_string($item)) {
                    $item = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $item);
                }
            });
        }

        $response = [
            'data'         => $data,
            'total'        => $query->total(),
            'current_page' => $query->currentPage(),
            'last_page'    => $query->lastPage(),
            'per_page'     => $query->perPage(),
            'from'         => $query->firstItem(),
            'to'           => $query->lastItem(),
            'first_record' => $first_record_data,
        ];

        // Return the response
        return $response;
    }

    public function storeLunch($lastRecord)
    {
        if (!$lastRecord) {
            return Response::json(['error' => 'You need to be clocked in to go to lunch.'], 400);
        }
        
        //lunch clockin
        if (request()->get('lunch') && request()->get('type') == 'in' && $lastRecord->lunch) {
            $end = new Carbon($lastRecord->time);
            $end->addMinutes(30);
            
            //to late 
            if ($end < Carbon::now()) {
                $out = TimeLog::create(['type' => 'out', 'lunch' => 1, 'time' => $end]);
                $in = TimeLog::create(['type' => 'in', 'time' => Carbon::now()->addSeconds(1)]);
                return Response::json($in);
            } else {
                //on time
                $out = TimeLog::create(['type' => 'out', 'lunch' => 1, 'time' => Carbon::now()]);
                $in = TimeLog::create(['type' => 'in', 'time' => Carbon::now()->addSeconds(1)]);
                return Response::json($in);
            }
        }
        
        //if has had lunch today
        $lastLunch = TimeLog::LastlunchRecord()->first();
        if ($lastLunch) {
            $lastLunchTime = new Carbon($lastLunch->time);
            if ($lastLunchTime->isToday()) {
                return Response::json(['error' => 'You have had your lunch for today.'], 400);
            }
        }

        //lunch clockout
        if (request()->get('lunch') && request()->get('type') == 'out' && !$lastRecord->lunch && $lastRecord->type == 'in') {
            //lunch clockout
            $out = TimeLog::create(['type' => 'out']);
            $in = TimeLog::create(['type' => 'in', 'lunch' => 1, 'time' => Carbon::now()->addSeconds(1)]);
            return Response::json($in);
        }

        return Response::json(['error' => 'You need to be clocked in to go to lunch.'], 400);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store()
    {
        Log::info('TimeLogControllerRESTv1::store called');
        
        // Clock in or out
        // We need to validate the request
        // if a user is clocked in at the moment for the current day
        // he can't clock in again, same applies if he is clocked out and tries to clock out again
        // for this we will need the last record

        if (request()->has('new_record_request')) {
            // The user has requested to record a previous record
            // this also needs approval, so an approval request will
            // be created for it
            $record = new TimeLog(request()->only('type', 'new_record_request', 'time'));
            $record->pending_change_request = 1;

            if (!$record->save()) {
                return Response::json(['errors' => $record->errors->all()], 400);
            }

            $change_request = TimeLogChangeRequest::create(['time_log_id' => $record->id, 'time' => $record->time]);
            if (!$record->exists) {
                return Response::json(['errors' => $record->errors->all()], 400);
            }
            return $record;
        }

        $lastRecord = TimeLog::lastRecord()->first();
        if (request()->get('lunch')) {
            return $this->storeLunch($lastRecord);
        }

        if ($lastRecord && $lastRecord->type == request()->get('type')) {
            return Response::json(['error' => 'You are already clocked ' . $lastRecord->type], 400);
        }
        
        return TimeLog::create(request()->only('type'));
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        $timeLog = TimeLog::find($id);

        if (!$timeLog) {
            return Response::json(['error' => 'Time log not found'], 404);
        }

        return Response::json($timeLog);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id)
    {
        $timeLog = TimeLog::find($id);

        if (!$timeLog) {
            return Response::json(['error' => 'Time log not found'], 404);
        }

        $timeLog->update(request()->all());

        return Response::json($timeLog);
    }

    /**
     * Check if user has had lunch today
     *
     * @return Response
     */
    public function checkLunchStatus()
    {
        $lastLunch = TimeLog::LastlunchRecord()->first();
        $hasHadLunchToday = false;
        
        if ($lastLunch) {
            $lastLunchTime = new Carbon($lastLunch->time);
            $hasHadLunchToday = $lastLunchTime->isToday();
        }
        
        return Response::json(['hasHadLunchToday' => $hasHadLunchToday]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function destroy($id)
    {
        $timeLog = TimeLog::find($id);

        if (!$timeLog) {
            return Response::json(['error' => 'Time log not found'], 404);
        }

        $timeLog->delete();

        return Response::json(['success' => true, 'message' => 'Time log deleted']);
    }
}
