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

use App\Http\Controllers\Controller;
use App\Models\CompanyWorkerTimesheet;
use App\Models\Projects;
use App\Models\ProjectSupervisors;
use App\Models\Worker;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Traits\UserTraits;
use Prophecy\Doubler\Generator\Node\ReturnTypeNode;
use App\Traits\CreateMobileNotificationTraits;

class WorkerTimelog 
{
    use UserTraits, CreateMobileNotificationTraits;

    public function fetchSupervisorsTimelogs($payload)
    {
        $current_date = Carbon::parse($payload->currentDate)->toDateString();
        $supervisorsList = ProjectSupervisors::select(
            DB::raw("CONCAT(workers.first_name,' ',workers.last_name) AS display_name"),
            'workers.id as worker_id',
            'company_workers_timesheet.id as id',
            'projects.id as project_id',
            'projects.name',
            'projects.description',
            'projects.clock_in',
            'projects.clock_out',
            'projects.location',
            DB::raw('IFNULL(company_workers_timesheet.id,false) as timesheet_id'),
            'company_workers_timesheet.date',
            'company_workers_timesheet.status',
            'company_workers_timesheet.total_hours',
            'company_workers_timesheet.time_in',
            'company_workers_timesheet.time_out',
        )
            ->leftJoin('projects', 'projects.id', 'project_supervisors.project_id')
            ->join('workers', 'workers.id', 'project_supervisors.user_id')
            ->leftJoin('company_workers_timesheet', 'company_workers_timesheet.worker_id', 'workers.id')
            ->where('company_workers_timesheet.role', 'supervisor')
            ->orWhereNull('company_workers_timesheet.role')
            ->whereRaw('? BETWEEN project_supervisors.date_from and project_supervisors.date_to', [$current_date])
            ->get()
            ->toArray();

            $supervisors = $this->getWorkerId($this->unique_multidim_array($supervisorsList, 'worker_id'));

            $supervisorDaySchedules = array();
            foreach ($supervisors as $supervisor) {
                $projects = array();
                $overallStatus = 'Absent';
                $submittedProject = 0;
                $modificationProject = 0;
                $existingSubmission = array();
    
                foreach ($supervisorsList as $project) {
                    if ($supervisor['worker_id'] == $project['worker_id']) {
                        if ($current_date == $project['date']) {
                            array_push($projects, [
                                'timesheet_id' => $project['timesheet_id'],
                                'project_name' => $project['name'],
                                'date' => $project['date'],
                                'project_clock_in' => $project['clock_in'],
                                'project_clock_out' => $project['clock_out'],
                                'submitted_clock_in' => $project['time_in'],
                                'submitted_clock_out' => $project['time_out'],
                                'total_hours' => $project['total_hours'],
                                'status' => $project['status'],
                                'project_id' => $project['project_id'],
                            ]);
                            array_push($existingSubmission, $project['project_id']);
                            $submittedProject++;
                        }
    
                    }
    
                }
    
                $projects = array_merge($projects, $this->getSupervisorsProject($supervisor['worker_id'], $existingSubmission, $current_date));
    
                array_push($supervisorDaySchedules, [
                    'worker_id' => $supervisor['worker_id'],
                    'display_name' => $supervisor['display_name'],
                    'projects' => $projects,
                    'project_count' => count($projects),
                    'existing' => $existingSubmission,
                ]);
            }
            return $supervisorDaySchedules;
    }

    public function newFetchSupervisorsTimelogs($payload)
    {
        $projectManagerId = Auth::user()->id;
        $current_date     = Carbon::parse($payload->currentDate)->toDateString();
        $companyID        = $this->getCurrentUser()->company_id;

        $listOfSupervisorPerProject = ProjectSupervisors::select(
            'project_supervisors.id',
            'project_supervisors.project_id',
            'project_supervisors.user_id',
            DB::raw("CONCAT(workers.first_name,' ', workers.last_name) AS display_name"),
            'workers.id as worker_id',
            'company_users.company_id',
        )
        ->join('workers', 'workers.id', 'project_supervisors.user_id')
        ->join('company_users', 'company_users.worker_id', 'project_supervisors.user_id')
		->join('projects', 'projects.id', 'project_supervisors.project_id')
        ->whereRaw('? BETWEEN project_supervisors.date_from and project_supervisors.date_to', [$current_date])
        ->where('company_users.company_id', $companyID)
        ->where('projects.project_manager_id', '=', $projectManagerId)
        ->get();
        
        if(!$listOfSupervisorPerProject){
            return null;
        }

        $holdSupervisorsWithProject = [];
        $holdSupervisorsID = [];
        $finalData = [];

        // get the supervisor, while removing the duplication
        foreach($listOfSupervisorPerProject as $supervisor)
        {
            $inArray = in_array($supervisor->user_id, $holdSupervisorsID);
            if (!$inArray)
            {
                array_push($holdSupervisorsID, $supervisor->user_id);
                array_push(
                    $holdSupervisorsWithProject, 
                    [
                        'displayName' => $supervisor->display_name,
                        'supervisorId' => $supervisor->worker_id,
                        'projectLength' =>  $this->getSupervisorProjectLength($supervisor->user_id, $projectManagerId, $current_date), 
                    ]
                );
            }
        }   

        return $holdSupervisorsWithProject;
    }

    public function countProjectOfSupervisor($supervisorID, $data){
        $count = 0;
        foreach($data as $project){
            if($project->user_id == $supervisorID){
                $count++;
            }
        }
        return $count;
    }

    public function getSupervisorProjectLength($supervisorId, $projectManagerId, $date)
    {
        return ProjectSupervisors::query()
                ->whereRelation('project', 'project_manager_id', '=', $projectManagerId)
                ->where(
                    [
                        ['user_id',  '=',   $supervisorId],
                        ['date_from', '<=', $date],
                        ['date_to',  '>=',  $date],
                    ]
                )
                ->count();
    }

    public function requestTimelogModification($payload)
    {
        $id = $payload->timesheet_id;

        $data = array(
            'request_modification_message' => $payload->message,
            'status' => 'request modification',
            'role' => 'supervisor',
        );
        $result = CompanyWorkerTimesheet::where('id', $id)->update($data);

        if($result){
            $mobileNotificationData = array(
				'worker_id' =>$payload->worker_id,  //supervisor id
				'message' => 'A project manager is requesting to modify your Time Log.',
				'type' => 'user',
				'link' => '/company/supervisor/timelogs',
			);
			$this->createMobileNotification($mobileNotificationData);

            return response()->json(['success' => 'Data updated successfully.'])->setStatusCode(201);
        }

        return response()->json(['error' => 'Something went wrong.'])->setStatusCode(201);
    }

    public function createTimelogWithNote($payload)
    {

        $worker_rate = Worker::select('rate')->where('id', $payload->worker_id)->first();
        $project_name = Projects::select('name')->where('id', $payload->project_id)->first();

        $data = array(
            'worker_id' => $payload->worker_id,
            'company_id' => $this->getCurrentUser()->company_id,
            'date' => Carbon::parse($payload->date),
            'reference_id' => $payload->project_id,
            'rate' => $worker_rate->rate,
            'description' => "Hours rendered for project " . $project_name->name,
            'request_modification_message' => $this->getCurrentUserName() . " : " . $payload->message,
            'status' => 'request modification',
            'time_in' => '00:00',
            'time_out' => '00:00',
            'total_hours' => 0,
            'type' => 'project',
            'role' => 'supervisor',
        );

        $submitTimelog = CompanyWorkerTimesheet::create($data);

        if($submitTimelog){
            return response()->json(['success' => 'Data created successfully.'])->setStatusCode(201);
        }

        return response()->json(['error' => 'Something went wrong.'])->setStatusCode(201);
    }

    public function approved($payload)
    {

        $id = $payload->id;

        $dateToApptoved =  Carbon::parse($payload->date)->format('Y-m-d');
        $dateToday =  Carbon::now()->format('Y-m-d');

        if($dateToday < $dateToApptoved){
            return response()->json(['error' => 'Unable to proceed, cannot approved future dates.'])->setStatusCode(201);
        }   

        if(!$id){
            return response()->json(['error' => 'Cannot approved. The supervisor has not yet submitted its timelog.'])->setStatusCode(201);
        }

        $result = CompanyWorkerTimesheet::where('id', $id)
            ->update([
                'status' => 'approved',
            ]);

        if($result){
            $mobileNotificationData = array(
				'worker_id' =>$payload->worker_id, //supervisor id
				'message' => 'A project manager has approved your Time Log.',
				'type' => 'user',
				'link' => '/company/supervisor/timelogs',
			);
			$this->createMobileNotification($mobileNotificationData);


            return response()->json(['success' => 'Data approved successfully.'])->setStatusCode(201);
        }

        return response()->json(['error' => 'Something went wrong.'])->setStatusCode(201);
    }

    public function unique_multidim_array($array, $key)
    {
        $temp_array = array();
        $i = 0;
        $key_array = array();

        foreach ($array as $val) {
            if (!in_array($val[$key], $key_array)) {
                $key_array[$i] = $val[$key];
                $temp_array[$i] = $val;
            }
            $i++;
        }
        return $temp_array;
    }
    public function getWorkerId($array)
    {
        $ids = array();
        foreach ($array as $item) {
            array_push($ids, ['worker_id' => $item['worker_id'], 'display_name' => $item['display_name']]);
        }
        return $ids;
    }

    public function getSupervisorsProject($worker_id, $existing_project_id, $date)
    {
        $pendingSchedules = array();
        $projects = ProjectSupervisors::select(
            'projects.clock_in as time_in',
            'projects.clock_out as time_out',
            'projects.id as project_id',
            'projects.name',
            'projects.description',
            'projects.clock_in',
            'projects.clock_out',
            'projects.location'
        )
            ->leftJoin('projects', 'projects.id', 'project_supervisors.project_id')
            ->join('workers', 'workers.id', 'project_supervisors.user_id')
            ->where(function ($query) use ($date) {
                $query->whereRaw('? BETWEEN project_supervisors.date_from and project_supervisors.date_to', [$date])
                    ->orWhere(function ($query) use ($date) {
                        $query->whereDate('project_supervisors.date_from', '<=', $date)
                            ->whereDate('project_supervisors.date_to', '>=', $date);
                    });
            })
        /*   ->orWhereRaw('(project_supervisors.date_from,  project_supervisors.date_to) IN ', [$date]) */
            ->where('project_supervisors.user_id', $worker_id)
            ->get()
            ->toArray();
        foreach ($projects as $project) {

            if (!in_array($project['project_id'], $existing_project_id)) {
                array_push($pendingSchedules, [
                    'timesheet_id' => null,
                    'project_name' => $project['name'],
                    'date' => $date,
                    'project_clock_in' => $project['clock_in'],
                    'project_clock_out' => $project['clock_out'],
                    'submitted_clock_in' => $project['time_in'],
                    'submitted_clock_out' => $project['time_out'],
                    'total_hours' => 0,
                    'status' => 'pending',
                    'project_id' => $project['project_id'],
                ]);
            }
            # code...
        }

        return $pendingSchedules;
    }

    public function fetchSupervisorProjects($supervisorID, $payload)
    {
        $date = \Carbon\Carbon::parse($payload->date)->format('Y-m-d');
        
        $projects = ProjectSupervisors::select(
                'projects.id as project_id',
                'projects.name',
                'projects.clock_in',
                'projects.clock_out',
                'company_workers_timesheet.worker_id',
                'company_workers_timesheet.date',
                'company_workers_timesheet.status',
                'company_workers_timesheet.total_hours',
                'company_workers_timesheet.time_in',
                'company_workers_timesheet.time_out',
                DB::raw('IFNULL(company_workers_timesheet.id, null) as timesheet_id'),
            )
            ->join('projects', 'projects.id', 'project_supervisors.project_id')
            ->leftJoin('company_workers_timesheet', function ($query) use ($date){
                $query->on('company_workers_timesheet.reference_id', '=', 'projects.id')
                ->where('company_workers_timesheet.date', $date);
            })
            ->where('project_supervisors.date_to', '>=', $date)
            ->where('company_workers_timesheet.worker_id', '=', $supervisorID)
            ->get();

        return $projects;
    }

}
