<?php

namespace App\Modules\Company\Borrow\Requests;

use App\Models\BorrowCancelled;
use App\Models\BorrowPendingWorkers;
use App\Models\BorrowRequest;
use App\Models\LoanPendingWorkers;
use App\Models\Search;
use App\Traits\CreateUserActionTraits;
use App\Traits\UserTraits;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Events\Company\CreateNotificationEvent;

class CancelPendingRequest
{
    use CreateUserActionTraits, UserTraits;

    public function cancel($payload)
    {
        $selectedpendingworkers = $payload->selectedpendingworkers;
        $workerCompanyIdForLogs = [];

        foreach ($selectedpendingworkers as $selectedpendingworker) {
            // Start transaction
            DB::beginTransaction();

            // START FOR BORROW
            $id = $selectedpendingworker['id']; // borrow_pending_workers primary id
            $borrowPendingWorkerTransaction = $this->updateBorrowPendingWorkerStatus($id);

            // fetch borrow request details
            $borrowRequest = BorrowRequest::select(
                'borrow_requests.id', 'borrow_requests.created_at as date_requested',
                'borrow_requests.requested_by',
                'borrow_requests.note as requester_note',
                'borrow_pending_workers.search_id',
                'borrow_pending_workers.date_from', 'borrow_pending_workers.date_to',
                'borrow_pending_workers.worker_id', 'borrow_pending_workers.rate',
                'borrow_pending_workers.original_rate',
                'borrow_pending_workers.status')
                ->join('borrow_pending_workers', 'borrow_pending_workers.borrow_request_id', '=', 'borrow_requests.id')
                ->where('borrow_pending_workers.id', $id)
                ->limit(1)->get();

            // Check if borrow_pending_workers status is already approved
            $status = $borrowRequest[0]->status;
            if ($status == 'Approved') {
                return response()->json(['error' => 'Selected user already approved by the loaning company.'])->setStatusCode(201);
            } else if ($status == 'Declined') {
                return response()->json(['error' => 'Selected user already declined by the loaning company.'])->setStatusCode(201);
            }

            // Add cancelled borrow pending worker to borrow_cancelled_histories table
            $borrowerCompanyId = $this->getCurrentUser()->company_id; // borrower_company_id
            $dateRequested = $borrowRequest[0]->date_requested;
            $requestedBy = $borrowRequest[0]->requested_by;
            $dateFrom = $borrowRequest[0]->date_from;
            $dateTo = $borrowRequest[0]->date_to;
            $workerId = $borrowRequest[0]->worker_id;
            $rate = $borrowRequest[0]->rate;
            $originalRate = $borrowRequest[0]->original_rate;
            $cancelledBy = Auth::user()->id;
            $requesterNote = $borrowRequest[0]->requester_note;

            // preparing borrow pending worker to be saved on database
            $selectedPendingWorkerData = array(
                'borrower_company_id' => $borrowerCompanyId,
                'date_requested' => $dateRequested,
                'requested_by' => $requestedBy,
                'date_from' => $dateFrom,
                'date_to' => $dateTo,
                'rate' => $rate,
                'original_rate' => $originalRate,
                'worker_id' => $workerId,
                'cancelled_by' => $cancelledBy,
                'requester_note' => $requesterNote,
            );
            $borrowCancelledTransaction = $this->saveBorrowPendingWorkerToBorrowCancelledHistories($selectedPendingWorkerData);

            // Update Search Table
            $searchId = $borrowRequest[0]->search_id;
            $updateSearchTransaction = $this->updateItemOnSearchTable($searchId);

            // START FOR LOAN
            $id = $selectedpendingworker['id']; // loan_pending_workers primary id
            $LoanPendingWorkerTransaction = $this->updateLoanPendingWorkerStatus($id);

            // If there's an error or queries don't do their job, rollback!
            if (!$borrowPendingWorkerTransaction ||
                !$borrowCancelledTransaction ||
                !$updateSearchTransaction ||
                !$LoanPendingWorkerTransaction) {
                DB::rollBack();
            } else {
                DB::commit();
                // Only the commited worker will be lister in the reports
                array_push($workerCompanyIdForLogs, $selectedpendingworker['company_worker_id']);
            }
        }

        // Prepare reports description
        if (count($workerCompanyIdForLogs) > 1) {
            $lastEmployee = array_pop($workerCompanyIdForLogs);
            $workerCompanyIdForLogs = "Cancelled the request for Employees " . join(", ", $workerCompanyIdForLogs) . " and " . $lastEmployee;
        } else {
            $workerCompanyIdForLogs = "Cancelled the request for Employee " . join(", ", $workerCompanyIdForLogs);
        }

        // Process the db transation in saving logs
        $transactLogs = $this->createUserAction($workerCompanyIdForLogs);
        if ($transactLogs) {
            event(new CreateNotificationEvent("cancelled", "request", $id));
            DB::commit();
            return response()->json(['success' => 'Data saved successfully.'])->setStatusCode(201);
        } else {
            DB::rollBack();
            return response()->json(['error' => 'Something went wrong.'])->setStatusCode(201);
        }
    }

    public function updateBorrowPendingWorkerStatus($id)
    {
        $selectedPendingWorkerData = array(
            'status' => 'Cancelled',
        );
        return BorrowPendingWorkers::where('id', $id)
            ->where('status', 'Pending') // Only Pending status can be Cancelled
            ->update($selectedPendingWorkerData);
    }

    public function saveBorrowPendingWorkerToBorrowCancelledHistories($selectedPendingWorkerData)
    {
        return BorrowCancelled::create($selectedPendingWorkerData);
    }

    public function updateItemOnSearchTable($searchId)
    {
        $statusData = array(
            'status' => 'Available',
        );
        return Search::where('id', $searchId)->update($statusData);
    }

    public function updateLoanPendingWorkerStatus($id)
    {
        $selectedPendingWorkerData = array(
            'status' => 'Cancelled',
        );
        return LoanPendingWorkers::where('id', $id)
            ->where('status', 'Pending') // Only Pending status can be Cancelled
            ->update($selectedPendingWorkerData);
    }
}
