<?php
namespace App\Modules\Mobile\Worker;

use App\Models\Worker;
use App\Models\WorkerFile;
use App\Models\WorkAreaLists;
use App\Models\WorkerExperience;
use App\Models\CompanyBurdenRate;
use App\Models\EmailVerification;
use App\Jobs\Mobile\ProcessSendEmailForUpdateCompanyWorker;
use App\Traits\UserTraits;
use App\Traits\ValidatorTraits;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Intervention\Image\Facades\Image;
use Illuminate\Support\Facades\Validator;
use App\Traits\GoogleBucket as GoogleBucketTrait;
use App\Modules\RemoteStorage\GoogleBucketGateway;
use App\Http\Resources\Company\Worker as WorkerResource;


class Profile 
{
    use UserTraits, ValidatorTraits, GoogleBucketTrait;

    public $googleBucket;
    public function __construct(GoogleBucketGateway $googleBucket)
    {
        $this->googleBucket = $googleBucket;
    }

    public function getProfile($payload)
    {
        $id = Auth::user()->id;
        $workerData = Worker::select(
            'workers.id',
            'workers.worker_id',
            'workers.email_address',
            'workers.phone_num',
            'workers.first_name',
            'workers.last_name',
            'workers.profile_picture',
            'workers.street_address',
            'workers.city',
            'workers.state',
            'workers.zipcode',
            'workers.flat_rate',
            'workers.date_hired',
            'workers.distance',
            'workers.resume_file_name as resume',
            'company_users.availability_status',
            'company_users.company_id',
            'workers.additional_details',
            'worker_experiences.experience_id',
            'company_experiences.name as experience_name',
            'worker_experiences.experience as experience',
            'worker_experiences.expertise_id',
            'worker_experiences.expertise as expertise',
            'expertises.name as expertise_name')
            ->join('company_users', 'company_users.worker_id', '=', 'workers.id')
            ->leftJoin('worker_experiences', 'worker_experiences.worker_id', '=', 'workers.id')
            ->leftJoin('company_experiences', 'company_experiences.id', '=', 'worker_experiences.experience_id')
            ->leftJoin('expertises', 'expertises.id', '=', 'worker_experiences.expertise_id')
            ->with('work_area_lists:work_area_id,worker_id,name')
            ->with('roles:worker_id,role_id,name')
            ->with('files')
            ->where('workers.id', $id)
            ->get();
        return WorkerResource::collection($workerData)->response()->setStatusCode(201);
    }

    public function update($payload)
    {


        /*========================================================================================================
        Start Transaction
        ========================================================================================================*/
        DB::beginTransaction();

        /*========================================================================================================
        worker data
        ========================================================================================================*/

        $workerData = $this->getCurrentUser();

        $worker_id = $workerData->id;
        $company_id = $workerData->company_id;
        $first_name = ucfirst($payload->first_name);
        $last_name = ucfirst($payload->last_name);
        $profile_picture = $payload->profile_picture;
        $email_address = strtolower($payload->email_address);
        $phone_num = '+1' . str_replace(array('-', '(', ')', ' '), '', $payload->phone_num);
        $street_address = $payload->street_address;
        $city = $payload->city;
        $state = $payload->state;
        $zipcode = $payload->zipcode;
        $other_experience = $payload->other_experience;
        $other_expertise = $payload->other_expertise;
        $additionalDetails = $payload->additional_details;
        $additionalDetails = $additionalDetails == 'null' || $additionalDetails == ''? '' : $additionalDetails;
        $willingDistance = $payload->willing_distance;

        /*========================================================================================================
        worker experiences data
        ========================================================================================================*/
        $expertise = $payload->expertise;
        $level_of_experience = $payload->level_of_experience;
        $worker_type = 'worker';

        /*========================================================================================================
        worker areas of work data
        ========================================================================================================*/
        $areas_of_work = $payload->areas_of_work;
        /*   return $areas_of_work; */

        /*========================================================================================================
        Validate Query Params
        ========================================================================================================*/
        $rules = array(
            'first_name' => 'required|max:50',
            'last_name' => 'required|max:50',
            'email_address' => 'required|unique:workers,email_address,' . $worker_id . '|max:191',
            'phone_num' => 'required|max:50',
            'street_address' => 'required|max:50',
            'city' => 'required|max:50',
            'state' => 'required|max:50',
            'zipcode' => 'required|string|min:5|max:5',
            'expertise' => 'required',
            'level_of_experience' => 'required',
            'willing_distance' => 'required',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        // Certificates file name validation
        if($payload->files_names){

            $filesValidator = $this->validateCertificateFiles($payload);
            if($filesValidator){
                return $filesValidator;
            }

            $fileNamesValidator = $this->validateCerficatesName($payload, $worker_id);
            if($fileNamesValidator){
                return $fileNamesValidator;
            }
        }

        // /*========================================================================================================
        // Check if email was changed then send an email
        // ========================================================================================================*/
        // $worker = Worker::where('id', $worker_id)->first();

        // if (strtolower($worker->email_address) != $email_address) {
        //     // SavVerificatione Email
        //     $code = hash('sha256', $plainTextToken = Str::random(80));
        //     $worker_data = array(
        //         'company_id' => $company_id,
        //         'user_id' => $worker_id,
        //         'email_address' => $email_address,
        //         'code' => $code,
        //         'type' => 'Company Email Update',
        //     );
        //     EmailVerification::where('company_id', $company_id)->where('user_id', $worker_id)->delete();
        //     EmailVerification::create($worker_data);
        //     $verification_url = stripslashes(env('API_BASE_URL') . '/api/verify-email?code=' . $code);
        //     $worker_data = [
        //         'email_address' => $email_address,
        //         'first_name' => $first_name,
        //         'last_name' => $last_name,
        //         'verification_url' => $verification_url,
        //     ];
        //     ProcessSendEmailForUpdateCompanyWorker::dispatch($email_address, $worker_data)->onQueue('sendemail');
        // }

        /*========================================================================================================
        Profile picture
        ========================================================================================================*/

        $profilePicture = $payload->profile_picture;
        $hasProfile = $profilePicture == 'null' || $profilePicture == ''?  false : true;
        $profilePicture = $hasProfile? $payload->profile_picture : null;

        // profile picture
        if ($hasProfile) {
            $isBase64Profile = $payload->isBase64Profile == false || $payload->isBase64Profile == 'false'? false : true;
            if(!$isBase64Profile){
                $this->removeUploadedFile($payload->previousProfileLink, $this->googleBucket); //remove the previous link
            }
            $image_64 = $profilePicture;
            $extension = explode('/', explode(':', substr($image_64, 0, strpos($image_64, ';')))[1])[1]; // .jpg .png
            $image = explode(',', $image_64)[1];
            $filePath = $this->createUniqueImageNameWorker($company_id, $extension);
            $this->uploadBase64Image($image, $filePath, $this->googleBucket);

            $profilePicture = $filePath;
        }

        /*========================================================================================================
        preparing worker data to be saved on database
        ========================================================================================================*/
        $worker_data = array(
            'email_address' => $email_address,
            'first_name' => $first_name,
            'last_name' => $last_name,
            'street_address' => $street_address,
            'city' => $city,
            'state' => $state,
            'zipcode' => $zipcode,
            'additional_details' => $additionalDetails,
            'phone_num' => $phone_num,
            'distance' => $willingDistance,
            'email_code' => null,
            'mobile_code' => null,
        );

        if($hasProfile){
            $worker_data['profile_picture'] = $profilePicture; //add profile link
        }
        $workerTransaction = $this->updateWorker($worker_id, $worker_data);

        // CREATE WORKER FILES
        if($payload->files_names){
            $fileNames = $payload->files_names;
            $indexCount = 0;
            foreach($fileNames as $key => $name){
                $filePayloadName = 'files.'. $indexCount;
                $resumeExtension = $payload->file($filePayloadName)->extension();
                $resumeFilePathName = $this->createUniqueFileName(1, $resumeExtension);

                $this->uploadNewFile($payload, $resumeFilePathName, $filePayloadName, $this->googleBucket);
                $indexCount++;
                $newCertificate = array(
                    'worker_id' => $worker_id,
                    'name' => str_replace ( '.'.$resumeExtension, '', $name), //remove the extension '.pdf'
                    'location' => $resumeFilePathName
                );
                WorkerFile::create($newCertificate);
            }
        }

        /*========================================================================================================
        preparing worker experiences data to be saved on database
        ========================================================================================================*/
        // check worker experience if has one
        $workerExperienceData = $this->checkWorkerExperience($worker_id);

        $test = true;
        if ($workerExperienceData && !($level_of_experience == $workerExperienceData->experience_id)) {
            //different epxerience meaning change the worker experience
            $newCompanyExperienceBurdenRateData = $this->getNewCompanyExperienceBurdenRateData($level_of_experience);

            $newWorkerExperienceData = array(
                'experience_id' => $level_of_experience,
                'expertise_id' => $expertise,
                'is_worker' => 'true',
                'experience' => $other_experience,
                'expertise' => $other_expertise,
                'burden_rate_id' => $newCompanyExperienceBurdenRateData->id,
            );

            $test = 'newExperience';

        } else {
            $newWorkerExperienceData = array(
                'expertise_id' => $expertise,
                'is_worker' => 'true',
                'experience' => $other_experience,
                'expertise' => $other_expertise,
            );

            $test = 'NotnewExperience';

        }
        $workerExperienceTransaction = WorkerExperience::where('worker_id', $workerData->id)->update($newWorkerExperienceData);

        /*========================================================================================================
        worker areas
        ========================================================================================================*/
        $company_work_area_list_transaction = true;
        if (is_array($areas_of_work) || is_object($areas_of_work)) {
            //delete the old data
            $current_worker_work_areas_transaction = $this->deleteCurrentWorkerAreas($worker_id);

            //create individually
            foreach ($areas_of_work as $area_of_work) {
                $worker_areas_of_work_data = array(
                    'work_area_id' => $area_of_work,
                    'worker_id' => $worker_id,
                    'worker_type' => $worker_type,
                );
                $company_work_area_list_transaction = $this->saveWorkerWorkAreas($worker_areas_of_work_data);
            }
        }

        /*========================================================================================================
        If there's an error or queries don't do their job, rollback!
        ========================================================================================================*/
        if (!$workerTransaction ||
            !$workerExperienceTransaction ||
            !$company_work_area_list_transaction) {
            DB::rollBack();
            return response()->json(
                ['error' => 'Server error.',
                    'workerTransaction' => $workerTransaction,
                    'workerExperienceTransaction' => $workerExperienceTransaction,
                    'current_worker_work_areas_transaction' => $current_worker_work_areas_transaction,
                    'company_work_area_list_transaction' => $company_work_area_list_transaction,
                    'test' => $test,
                ]);
        } else {
            DB::commit();
            return response()->json(['success' => 'Data updated successfully.', 'test' => $test])->setStatusCode(201);
        }

    }

    public function updateWorker($id, $workerData)
    {
        return tap(Worker::where('id', $id))->update($workerData)->first();
    }
    
    public function updateWorkerExperience($id, $worker_experiences_data)
    {
        return WorkerExperience::where('worker_id', $id)->update($worker_experiences_data);
    }

    public function deleteCurrentWorkerAreas($id)
    {
        return WorkAreaLists::where('worker_id', $id)
            ->where('work_area_lists.worker_type', 'worker')
            ->delete();
    }

    public function saveWorkerWorkAreas($worker_areas_of_work_data)
    {
        return WorkAreaLists::create($worker_areas_of_work_data);
    }

    public function checkWorkerExperience($workerID)
    {
        return WorkerExperience::where('worker_id', $workerID)->first();
    }

    public function getNewCompanyExperienceBurdenRateData($experienceID)
    {
        return CompanyBurdenRate::where('company_experience_id', $experienceID)->first();
    }

}
