<?php

namespace App\Modules\Company\BorrowCart;

use Illuminate\Support\Facades\DB;
use App\Models\Search;
use App\Models\CompanyCart;
use App\Traits\ValidatorTraits;
use App\Traits\UserTraits;

class UpdateCartRequestDate{

    use ValidatorTraits, UserTraits;

    public function update($payload){

        $rules = array(
            'cart_id' => 'required',
            'worker_id' => 'required',
            'date_from' => 'required',
            'date_to' => 'required',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $companyID = $this->getCurrentUser()->company_id;
        $dateStart = $payload->date_from;
        $dateEnd = $payload->date_to;
        $workerID = $payload->worker_id;

        $isNewDateInConflict = $this->isNewDateInConflict($dateStart, $dateEnd, $companyID, $workerID); //empty means not applicable

        if($isNewDateInConflict < 1){
            return response()->json(['errors' => ['The new duration date is in conflict with the workers schedule. Please input another dates.']], 201);
        }   

        $cartID = $payload->cart_id;
        $newCartData = array(
            'date_from' => $dateStart,
            'date_to' => $dateEnd,
        );

        $updateTransaction = $this->updateCart($cartID, $newCartData);
        
        if($updateTransaction){
            return response()->json(['success' => ['Duration successfully updated.']], 201);
        }

        return response()->json(['errors' => ['Something went wrong while updating the date duration. Please try again later.']], 201);

    }


    public function isNewDateInConflict($dateStart, $dateEnd, $companyID, $workerID)
    {
        return Search::select(
            'search.id',
            'search.worker_id',
            'search.worker_company_id',
            'search.zip_code as zipcode',
            'search.hourly_rate as rate',
            'search.date_from',
            'search.date_to',
        )
        ->join('workers', 'workers.id', '=', 'search.worker_id')
        ->join('company_users', 'company_users.worker_id', '=', 'search.worker_id')
        // ->where('company_users.availability_status', 'for-lease')
        ->whereIn('company_users.availability_status', ['for-lease', 'reserved'])
        ->where('search.worker_id', $workerID)
        ->whereIn('search.status', ['Available', 'Requested', 'Haulted'])
        ->whereNotExists(function ($query) use ($companyID, $dateStart, $dateEnd) {
            $query->select(DB::raw(1))
                ->from('borrow_pending_workers')
                ->join('borrow_requests', 'borrow_requests.id', '=', 'borrow_pending_workers.borrow_request_id')
                ->whereRaw('borrow_pending_workers.worker_id = search.worker_id')
                ->whereIn('borrow_pending_workers.status', ['Approved'])
                ->where(function ($query) use ($companyID, $dateStart, $dateEnd) {
                    $query->where('borrow_requests.borrower_company_id', $companyID)
                    ->where('borrow_pending_workers.date_from', $dateStart)
                    ->orWhere('borrow_pending_workers.date_to', $dateEnd)
                    ->orWhereBetween('borrow_pending_workers.date_from', [$dateStart, $dateEnd])
                    ->orWhereBetween('borrow_pending_workers.date_to', [$dateStart, $dateEnd])
                    ->orWhereRaw('? BETWEEN borrow_pending_workers.date_from and borrow_pending_workers.date_to', [$dateStart])
                    ->orWhereRaw('? BETWEEN borrow_pending_workers.date_from and borrow_pending_workers.date_to', [$dateEnd]);
                });
        })
        // Worker shoud not exist if the date is within the date she/he is borrowed
        ->whereNotExists(function ($query) use ($companyID, $dateStart, $dateEnd) {
            $query->select(DB::raw(1))
                ->from('borrow_approved_histories')
                ->whereRaw('borrow_approved_histories.worker_id = search.worker_id')
                ->where(function ($query) use ($companyID, $dateStart, $dateEnd) {
                    $query->where('borrow_approved_histories.borrower_company_id', $companyID)
                    ->where('borrow_approved_histories.date_from', $dateStart)
                    ->orWhere('borrow_approved_histories.date_to', $dateEnd)
                    ->orWhereBetween('borrow_approved_histories.date_from', [$dateStart, $dateEnd])
                    ->orWhereBetween('borrow_approved_histories.date_to', [$dateStart, $dateEnd])
                    ->orWhereRaw('? BETWEEN borrow_approved_histories.date_from and borrow_approved_histories.date_to', [$dateStart])
                    ->orWhereRaw('? BETWEEN borrow_approved_histories.date_from and borrow_approved_histories.date_to', [$dateEnd]);
                });
        })
        ->limit(5)
        ->count();
    }

    public  function updateCart($cartID, $data){
        return CompanyCart::where('id', $cartID)->update($data);
    }
}   