<?php

namespace App\Modules\Company\Employees;

use App\Modules\Company\Employees\Worker as WorkerModule;
use App\Events\Company\WorkerRateUpdatedEvent;
use App\Http\Controllers\Controller;
use App\Http\Resources\Company\BillableRateResource;
use App\Models\Worker;
use App\Models\Availabilities;
use App\Models\Search;
use App\Traits\SearchTraits;
use App\Traits\SortingTraits;
use App\Traits\CalculateBillableRateTrait;
use App\Traits\ValidatorTraits;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Events\Company\BulkUpdateBillableRateEvent;

class BillableRate extends WorkerModule
{
    use SortingTraits, SearchTraits, CalculateBillableRateTrait, ValidatorTraits;

    public function getBillableRates($payload)
    {
        $companyId = $this->getCurrentUser()->company_id;
        $sortField = $this->sortField($payload, 'first_name');
        $sortOrder = $this->sortOrder($payload, 'asc');
        $nameSearch = $this->searchField($payload->display_name);
        $workerIdSearch = $this->searchField($payload->worker_sys_id);
        $expertiseSearch = $payload->expertise_name;
        $experienceSearch = $payload->experience_name ? $payload->experience_name[0]: '';
        $areaOfWorkSearch = $payload->work_area_lists;
        $zipcodeSearch = $this->searchField($payload->zipcode);

        return BillableRateResource::collection(
            Worker::select(
                'workers.id as worker_id',
                'workers.worker_id as worker_sys_id',
                'workers.rate as billable_rate',
                'workers.flat_rate as original_rate',
                'workers.overhead_charge as overhead_amount',
                'workers.overhead_type',
                'companies.service_charge',
                'company_burden_rate.burden_rate',
                'company_burden_rate.burden_rate_type',
                'company_experiences.name as experience_name',
                DB::raw("CONCAT(workers.first_name,' ',workers.last_name) as display_name"),
                DB::raw('CAST(workers.rate + (workers.rate * (0.01 * companies.service_charge)) AS DECIMAL(6,2)) as search_rate')
            )
                ->join('worker_experiences', 'worker_experiences.worker_id', 'workers.id')
                ->join('company_experiences', 'company_experiences.id', 'worker_experiences.experience_id')
                ->join('company_burden_rate', 'company_burden_rate.id', 'worker_experiences.burden_rate_id')
                ->join('company_users', 'company_users.worker_id', 'workers.id')
                ->join('companies', 'companies.id', 'company_users.company_id')
                ->where('company_users.role_id', 5)
                ->whereNotNull('workers.email_verified_at')
                ->where('company_users.company_id', $companyId)
                ->when(!empty($nameSearch), function ($query) use ($nameSearch) {
                    return $query->where(function ($query) use ($nameSearch) {
                        $query->where('workers.first_name', 'LIKE', $nameSearch . '%')
                            ->orWhere('workers.last_name', 'LIKE', $nameSearch . '%')
                            ->orWhere(DB::raw('CONCAT(workers.first_name, " ", workers.last_name)'), 'LIKE', $nameSearch . '%');
                    });
                })
                ->when(!empty($workerIdSearch), function ($query) use ($workerIdSearch) {
                    return $query->where('workers.worker_id', 'LIKE', $workerIdSearch . '%');
                })
                ->when(!empty($expertiseSearch), function ($query) use ($expertiseSearch) {
                    return $query->whereIn('worker_experiences.expertise_id', $expertiseSearch);
                })
                ->when(!empty($experienceSearch), function ($query) use ($experienceSearch) {
                    // return $query->whereIn('company_experiences.name', $experienceSearch);
                    return $query->where('company_experiences.name', 'LIKE', $experienceSearch . '%');
                })
                ->when(!empty($zipcodeSearch), function ($query) use ($zipcodeSearch) {
                    return $query->where('workers.zipcode', 'LIKE', $zipcodeSearch . '%');
                })
                ->orderBy($sortField, $sortOrder)
                ->paginate(20)
        )
            ->response()
            ->setStatusCode(201);

    }
    public function getWorkerBillableRate($worker_id)
    {

        return Worker::select(
            'workers.worker_id',
            'workers.rate',
            'workers.flat_rate',
            'workers.overhead_charge',
            'workers.overhead_type',
            'companies.service_charge',
            'company_burden_rate.burden_rate',
            'company_burden_rate.burden_rate_type',
        )
            ->join('worker_experiences', 'worker_experiences.worker_id', 'workers.id')
            ->join('company_burden_rate', 'company_burden_rate.id', 'worker_experiences.burden_rate_id')
            ->join('company_users', 'company_users.worker_id', 'workers.id')
            ->join('companies', 'companies.id', 'company_users.company_id')
            ->where('company_users.worker_id', $worker_id)
            ->first();
    }
    public function UpdateBillbleRate($payload)
    {

        /* $rate               = $payload->rate; */
        $worker_id = $payload->id;
        $flat_rate = $payload->flat_rate;
        $overhead_amount = $payload->overhead;
        $overhead_type = $payload->overhead_type;

        $new_details = [
            "rate" => $overhead_type == "real" ? ($flat_rate + $overhead_amount) : ($flat_rate + ($flat_rate + (0.1 * $overhead_amount))),
            "overhead_charge" => $overhead_amount,
            "overhead_type" => $overhead_type,
        ];

        $worker_update = Worker::where('id', $worker_id)
            ->update($new_details);

        if (!$worker_update) {
            return ["success" => false];
        }

        return ["success" => true];
    }
    public function getBillRate($payload, $worker_id)
    {
        $worker_id = $payload->worker_id ? $payload->worker_id : $worker_id;
        return Worker::select(
            'workers.id as worker_id',
            'workers.flat_rate as original_rate',
            'workers.overhead_charge as overhead_amount',
            'workers.worker_id as worker_sys_id',
            'workers.overhead_type',
            'companies.service_charge',
            DB::raw("CONCAT(workers.first_name,' ',workers.last_name) as display_name"),
            'companies.service_charge',
            'company_burden_rate.burden_rate',
            'company_burden_rate.burden_rate_type',

        )
            ->join('worker_experiences', 'worker_experiences.worker_id', 'workers.id')
            ->join('company_burden_rate', 'company_burden_rate.id', 'worker_experiences.burden_rate_id')
            ->join('company_users', 'company_users.worker_id', 'workers.id')
            ->join('companies', 'companies.id', 'company_users.company_id')
            ->where('company_users.worker_id', $worker_id)
            ->first();
    }
    public function updateWorkersBillableRate($payload)
    {
        // validate query params
        $rules = array(
            'overheadAmount' => 'required',
            'overheadType' => 'required',
            'hourly_rate' => 'required',
            'service_charge' => 'required',
            'burden_rate' => 'required',
            'burden_rate_type' => 'required',
            'worker_id' => 'required',
        );

        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $computationTransaction = $this->newComputationOfBillableRate($payload);

        if(!$computationTransaction){
            return response()->json([
                'errors' => 'Something went wrong while computing rates. Please Try again later', 
                'computationTransaction' => $computationTransaction], 
                201);
        }

        $updateWorkerRates = array(
            'flat_rate' => $computationTransaction->originalRate,
            'rate' => $computationTransaction->billableRate, 
            'overhead_charge' => $computationTransaction->overHeadAmount,
            'overhead_type' => $computationTransaction->overHeadType,
        );

        $updateWorkerTransaction = Worker::where('id', $payload->worker_id)->update($updateWorkerRates);

        $updateAvailabilityRate = array(
            'rate' => $computationTransaction->loadedRate,
        );

        $updateAvailabiliiesTransaction = $this->updateAvailabilities($payload->worker_id, $updateAvailabilityRate);

        $searchData = array(
            'original_rate' => $computationTransaction->originalRate,
            'hourly_rate' => $computationTransaction->searchRate, //serve as search rate, rate to be paid by loaner
        );

        // $updateSearchTransaction = Search::where('worker_id', $payload->worker_id)->first();
        $updateSearchTransaction = Search::where('worker_id', $payload->worker_id)->update($searchData);

        return response()->json(['success' => 'Worker billable rate updated successfully.', 
                'updateWorkerTransaction' => $updateWorkerTransaction,
                'updateSearchTransaction' => $updateSearchTransaction,
                'updateAvailabilityTransaction' => $updateAvailabiliiesTransaction,])->setStatusCode(201);
/*
        if($updateWorkerTransaction && $updateSearchTransaction && $updateAvailabiliiesTransaction){
            return response()->json(['success' => 'Worker billable rate updated successfully.'])->setStatusCode(201);
        }else{
            return response()->json([
                'errors' => 'Something went wrong while computing rates. Please Try again later', 
                'updateWorkerTransaction' => $updateWorkerTransaction,
                'updateSearchTransaction' => $updateSearchTransaction,
                'updateAvailabilityTransaction' => $updateAvailabiliiesTransaction,
            ], 201);
        }
        */
    }

    public function bulkUpdate($payload){
        $rules = array(
            'overheadAmount' => 'required',
            'overheadType' => 'required',
            'level_of_experience' => 'required',
        );

        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        //prepare data need on event
        $dataToPass = array(
            'level_of_experience' => $payload->level_of_experience,
            'overheadAmount' => $payload->overheadAmount,
            'overheadType' => $payload->overheadType,
            'userData' => $this->getCurrentUser(),
        );

        event(new BulkUpdateBillableRateEvent($dataToPass)); 
        return response()->json(['success' => 'Update billable rates are now being processed in the background.']);
    }

    public function updateAvailabilities($workerId, $updateAvailabilityRate){
        return Availabilities::where('worker_id', $workerId)
            ->where('worker_type', 'inhouse')
            ->update($updateAvailabilityRate);
    }
}
