<?php

namespace App\Modules\Company\Employees\Invitation;

use App\Jobs\Company\ProcessFileWorkerInvitation;
use App\Traits\CheckEmployeeCountAvailableTraits;
use App\Traits\CreateUserActionTraits;
use App\Traits\GenerateAndValidateWorkerID;
use App\Traits\RemoveDuplicateEmailTraits;
use App\Traits\ValidatorTraits;
use App\Models\Worker;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class FileInvitation 
{

    use GenerateAndValidateWorkerID, ValidatorTraits, CheckEmployeeCountAvailableTraits, RemoveDuplicateEmailTraits, CreateUserActionTraits;

    public function invite($payload)
    {
        if (request()->has('file')) {

            /* Validate file extension */
            $rules = array(
                'file' => 'required|max:50|mimes:csv,txt',
            );
            $validate = $this->validateRequest($payload, $rules);
            if ($validate) {
                return $validate;
            }

            $data = array_map('str_getcsv', file($payload->file));
            /* Validate header rows */
            if (!$this->checkHeaderFormat($data[0])) {
                return response()->json(['errors' => 'Invalid file format. Please use the given sample format'])->setStatusCode(200);
            };

            /* remove header  */
            unset($data[0]);

            $userData = $this->getCurrentUser();
            /* Validate maximum emp */
            $validate = $this->employeeCountValidation($userData->company_id, count($data));
            if ($validate) {
                return $validate;
            }

            /* removes duplicate value in the file */
            $data = $this->multi_unique($data);

            /* fetch all existing emails of a file, params = all email in first index  */
            $existing = $this->getExistingEmails(array_column($data, 0));

            /* return data : data who is not existing in the database  */
            $data = $this->cleanData($data, $existing);

            $hostname = Auth::user()->first_name . ' ' . Auth::user()->last_name;
            $compname = $userData->company_name;

            // Chunking file, divide into parts
            $chunks = array_chunk($data, 10);
            $batch = Bus::batch([])->onConnection('jobs_emails')->name('Employee File invitation')->onQueue('sendemail')->allowFailures(true)->dispatch();
            $unsend = [];

            foreach ($chunks as $key => $chunk) {
                $hold = [];
                foreach ($chunk as $user) {
                    $data = [];
                    $token = hash('sha256', $plainTextToken = Str::random(80));
                    //Check for empty columns [0] Email address , [1] Hourly Rate, [2] Date Hired (optional), [3] Admin verified
                    if (!$user[0] || !$user[1] || !$user[3]) {
                        if ($user[0] != "") {
                            //user who has incomplete data in the file
                            array_push($unsend, $user);
                        }
                    } else {
                        /* Prepare user data */
                        $data['email_address'] = strtolower($user[0]);
                        $data['rate'] = $user[1];
                        $data['date_hired'] = $user[2]? Carbon::parse($user[2]) : null;
                        $data['email_verification_code'] = strtolower($user[3]) == "yes" ? $token . "_admin_verified" : $token;
                        $data['first_name'] = 'Temp';
                        $data['last_name'] = 'Temp';
                        $data['zipcode'] = '00000';
                        $data['password'] = Hash::make(Str::random(8));
                        array_push($hold, (object) $data);
                    }

                }
                $batch->add(new ProcessFileWorkerInvitation($hold, $userData->company_id, $hostname, $compname));
            }
            $this->createUserAction("Invites employee using file upload");
            return response()->json(['batch' => $batch, 'duplicate' => $existing, 'unsend' => $unsend])->setStatusCode(201);
        }
        return response()->json(['errors' => 'No file uploaded.'])->setStatusCode(201);
    }

    public function checkEmail($email_address)
    {
        $data = Worker::where('email_address', $email_address)->first();
        return ($data) ? $email_address : false;
    }

    public function getBatch($id)
    {
        return Bus::findBatch($id);
    }

    public function multi_unique($data)
    {
        return $result = array_reverse(
            array_values(
                array_column(
                    array_reverse($data),
                    null,
                    0//email index
                )
            )
        );
    }

    public function getExistingEmails($emails)
    {
        return DB::table('workers')
            ->select('email_address')
            ->whereIn('email_address', (array) $emails)
            ->get();
    }

    public function checkHeaderFormat($headers)
    {
        if (count($headers) == 4) {
            if (in_array("Email Address", $headers) || in_array("Hourly Rate", $headers) || in_array("Date Hired", $headers) || in_array("Admin Verified", $headers)) {
                return true;
            }
            return false;
        }
        return false;
    }

    public function getWorkerInvitationFileFormat()
    {
        return Storage::disk('csv')->get('worker-invitation-format.csv');
    }
}
