<?php

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

use App\Exceptions\PermissionDeniedException;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use App\Http\Controllers\BaseController;
use App\Modules\Hr\Holiday;
use App\Modules\Hr\TimeLog;
use App\Modules\Hr\UserDetails;

class HolidayControllerREST extends BaseController
{
    public function index(Request $request)
    {
        $query = Holiday::query()->with('user');

        if (Auth::user()->hasPermission('access_hr')) {
            if ($request->has('user_id')) {
                $query->where('user_id', $request->input('user_id', getAuthUserId()));
            }

            if ($request->has('own') && $request->input('own') == 'true') {
                $query->where('user_id', getAuthUserId());
            }
        } else {
            // Allow all users to see approved holidays from everyone for dashboard calendar
            if ($request->input('status') == 'approved') {
                // Don't restrict by user_id for approved holidays - everyone can see them
            } else {
                // For non-approved holidays, force to see only own results
                $query->where('user_id', getAuthUserId());
            }
        }

        if ($request->input('status') && $request->input('status') != 'false') {
            $query->where('status', 'like', trim($request->input('status')));
        }

        if ($request->input('pending') && $request->input('pending') != 'false') {
            $query->where('status', 'like', 'pending');
        }

        if ($request->has('startDate') && $request->has('endDate')) {
            $query->period($request->input('startDate'), $request->input('endDate'));
        }

        // Paginate the results
        $query = $query->orderBy('start_date', 'desc')->paginate($request->input('limit', 100));

        // Prepare the response
        $response = [
            'data'         => $query->getCollection()->toArray(),
            'total'        => $query->total(),
            'current_page' => $query->currentPage(),
            'last_page'    => $query->lastPage(),
            'per_page'     => $query->perPage(),
            'from'         => $query->firstItem(),
            'to'           => $query->lastItem(),
        ];

        // Return the response
        return $response;
    }

    public function store(Request $request)
    {
        $holiday = Holiday::create($request->only('description', 'start_date', 'end_date', 'paid'));

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

        return $holiday;
    }

    public function update(Request $request, $id)
    {
        $holiday = Holiday::findOrFail($id);

        if ($holiday->status != 'pending' && $request->input('status') != 'cancelled') {
            throw new Exception('This record cannot be modified');
        }

        if (array_search($request->input('status'), ['approved', 'declined', 'cancelled']) !== FALSE) {
            // This requires admin acceess
            if (!Auth::user()->hasPermission('access_hr')) {
                throw new PermissionDeniedException();
            }
        }

        if ($request->input('status') == 'cancelled') {
            if ($holiday->user_id != Auth::user()->id && !Auth::user()->hasPermission('access_hr')) {
                throw new PermissionDeniedException();
            }

            // Delete all time logs for this holiday
            TimeLog::query()->where('holiday_id', $holiday->id)->delete();
        }

        if ($request->input('status') == 'approved') {
            // We need to create a time log for every day between the start_date and end_date
            // with the default start time and end time for the user...
            $user_details = UserDetails::findOrFail($holiday->user_id);
            $default_start_time = explode(':', $user_details->default_start_time);
            $default_end_time = explode(':', $user_details->default_end_time);

            $start_time = Carbon::parse($holiday->start_date)->hour((int)$default_start_time[0])->minute((int)$default_start_time[1])->second(0);
            $end_time = Carbon::parse($holiday->start_date)->hour((int)$default_end_time[0])->minute((int)$default_end_time[1])->second(0);

            // This is the last day of the holiday, when we reach this date we will stop
            $endDate = Carbon::parse($holiday->end_date)->hour(23)->minute(59)->second(59);

            while ($start_time->lte($endDate)) {
                if ($start_time->isWeekday()) {
                    TimeLog::create(['user_id' => $holiday->user_id, 'time' => $start_time->toDateTimeString(), 'type' => 'in', 'holiday_id' => $holiday->id]);
                    TimeLog::create(['user_id' => $holiday->user_id, 'time' => $end_time->toDateTimeString(), 'type' => 'out', 'holiday_id' => $holiday->id]);
                }
                // Increment the dates by one day
                $start_time->addDay();
                $end_time->addDay();
            }
        }

        // The only field that can be modified is the status...
        $holiday->fill($request->only('status'));

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

        return $holiday;
    }
}
