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

use App\Models\Company;
use App\Models\ProjectWorkersTimesheet;
use App\Models\TimesheetNotification;
use App\Modules\Mobile\Worker as WorkerModule;
use App\Traits\UserTraits;
use App\Traits\ValidatorTraits;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Support\Facades\Auth;

class Tasks 
{
    use UserTraits, ValidatorTraits;

    public function getTasks($payload)
    {
        $offset = $payload->offset ? $payload->offset : 0;
        $limit = $payload->limit;
        $workerId = Auth::user()->id;
        $filters = json_decode($payload->filters);

        $company = Company::companyInfo($this->getCurrentUser()->company_id);
        $period = [];

        if ($filters->isActive) {
            $period = [
                'from' => $filters->date->from,
                'to' => $filters->date->to,
            ];
        } else {
            $period = [
                'from' => Carbon::now()->toDateString(),
                'to' => Carbon::now()->add('30', 'days')->toDateString(),
            ];
        }

        $schedules = ProjectWorkersTimesheet::select(
            'project_workers_timesheet.id',
            'project_workers_timesheet.total_hours',
            'project_workers_timesheet.status',
            'projects.name as project_name',
            'companies.name as company_name',
            'projects.location',
            'projects.clock_in',
            'projects.clock_out',
            'project_workers_timesheet.date',
        )
            ->join('assigned_workers', 'assigned_workers.id', '=', 'project_workers_timesheet.project_worker_id')
            ->join('projects', 'assigned_workers.project_id', '=', 'projects.id')
            ->join('companies', 'companies.id', '=', 'projects.company_id')
        /*  ->where('project_workers_timesheet.status', 'pending') */
            ->where('project_workers_timesheet.worker_id', $workerId)
            ->where(function ($query) use ($period) {
                $query->whereBetween('project_workers_timesheet.date', [$period['from'], $period['to']])
                    ->orWhereIn('project_workers_timesheet.status', ['submitted', 'pending', 'request modification']);
            })
            ->whereNull('project_workers_timesheet.deleted_at')
            ->orderBy('date', 'ASC');

        $data = $schedules->get();
        $arrayData = $this->toDataArray($data); //worker time sheets data

        $firstDate = count($data) >= 1 ? Carbon::parse($data[0]->date) : Carbon::now();
        $lastDate = count($data) >= 1 ? Carbon::parse($data[0]->date)->add(40, 'days') : Carbon::now()->add(40, 'days');

        $gpDateParams = [
            "from" => $firstDate,
            "to" => $lastDate,
        ];

        $dateOptions = $this->GeneratePeriod((($filters && property_exists($filters, 'date')) ? $filters->date : ($firstDate->lt(Carbon::now()) ? $gpDateParams : false)), 'pending');
        $hits = [];


        foreach ($dateOptions['period'] as $key => $date) {

            //detect if the current date is existing on arrayData
            $needle = array_search(Carbon::parse($date)->toDateString(), array_column($arrayData, 'date'));
            $borrowerData = WorkerModule::getBorrowerCompany($workerId, Carbon::parse($date)->toDateString());

            if ($key >= $offset && $key <= $limit - 1) {
                if ($needle === false) {
                    $dateDiff = Carbon::parse($date)->gte(Carbon::parse(Carbon::now()->toDateString()));

                    if ($dateDiff) {
                        if ($borrowerData) {
                            array_push($hits, [
                                "id" => rand(10, 1000),
                                "company_name" => $borrowerData->name,
                                "project_name" => 'Stand by',
                                "status" => 'Stand by',
                                "clock_in" => null,
                                "clock_out" => null,
                                "date" => Carbon::parse($date)->toDateString(),
                                "plain_date" => $date,
                                "address" => 'Unavailable',
                                "location" => [
                                    "street_address" => $borrowerData->street_address,
                                    "city" => $borrowerData->city,
                                    "state" => $borrowerData->state,
                                    "zipcode" => (int) $borrowerData->zipcode,
                                    "report_to" => $borrowerData->contact_person_name,
                                    "tel_no" => $borrowerData->company_tel,
                                ],
                                "total_hours" => 00.0,
                                "has_project" => false,
                            ]);
                        } else {
                            array_push($hits, [
                                "id" => rand(10, 1000),
                                "company_name" => $company->name,
                                "project_name" => 'Stand by',
                                "status" => 'Stand by',
                                "clock_in" => null,
                                "clock_out" => null,
                                "date" => Carbon::parse($date)->toDateString(),
                                "plain_date" => $date,
                                "address" => 'Unavailable',
                                "location" => [
                                    "street_address" => $company->street_address,
                                    "city" => $company->city,
                                    "state" => $company->state,
                                    "zipcode" => (int) $company->zipcode,
                                    "tel_no" => $company->company_tel,
                                    "report_to" => $company->contact_person_name,
                                ],
                                "total_hours" => 00.0,
                                "has_project" => false,
                            ]);
                        }
                    }
                } else {
                    $currentStatus = in_array($arrayData[$needle]['status'], ['submitted', 'pending', 'request modification']);
                    $dateDiff = Carbon::parse($date)->gte(Carbon::parse(Carbon::now()->toDateString()));

                    // Update company details to borrower's
                    if ($borrowerData) {
                        $arrayData[$needle]['project_address'] = $borrowerData->street_address;
                        $arrayData[$needle]['project_address'] .= ', ' . $borrowerData->city;
                        $arrayData[$needle]['project_address'] .= ', ' . $borrowerData->state;
                        $arrayData[$needle]['project_address'] .= ', ' . $borrowerData->zipcode;
                    }

                    if ($dateDiff || $currentStatus) {
                        $arrayData[$needle]['has_project'] = true;
                        array_push($hits, $arrayData[$needle]);
                        $needle = false;
                    }
                }
            }
        }

        return [
            "count" => count($hits),
            "hits" => $hits,
            "Actual_Timesheet" => $arrayData,
            "generated_period" => $dateOptions,
            'arrayData' =>$arrayData,
            'period' =>$period,
            'queryfromProjectTimeSheet' => $data,
        ];
    }

    public function getHistory($payload)
    {
        $offset = $payload->offset ? $payload->offset : 0;
        $limit = $payload->limit;
        $workerId = Auth::user()->id;
        $filters = json_decode($payload->filters);
        $dateHired = Carbon::parse($this->getCurrentUser()->date_hired);
        $period = [];

        $company = Company::companyInfo($this->getCurrentUser()->company_id);

        if ($filters->isActive) {
            $period = [
                'from' => $filters->date->from,
                'to' => $filters->date->to,
            ];
        } else {
            $period = [
                'from' => Carbon::now()->subtract('30', 'days')->toDateString(),
                'to' => Carbon::parse($this->getServerTodayDate())->add('1', 'days')->toDateString(),
            ];
        }

        $schedules = ProjectWorkersTimesheet::select(
            'project_workers_timesheet.id',
            'project_workers_timesheet.total_hours',
            'project_workers_timesheet.status',
            'projects.name as project_name',
            'companies.name as company_name',
            'projects.location',
            'projects.clock_in',
            'projects.clock_out',
            'project_workers_timesheet.date',
        )
            ->join('assigned_workers', 'assigned_workers.id', '=', 'project_workers_timesheet.project_worker_id')
            ->join('projects', 'assigned_workers.project_id', '=', 'projects.id')
            ->join('companies', 'companies.id', '=', 'projects.company_id')
        /*  ->where('project_workers_timesheet.status', 'pending') */
            ->where('project_workers_timesheet.worker_id', $workerId)
            ->whereDate('project_workers_timesheet.date', '>=', $dateHired)
            ->whereNull('project_workers_timesheet.deleted_at')
            ->orderBy('date', 'ASC');

        $data = $schedules->get();
        $arrayData = $this->toDataArray($data);

        $dateOptions = $this->GeneratePeriod(($filters && property_exists($filters, 'date')) ? $filters->date : false, 'history');
        $dateOptions['period'] = array_reverse($dateOptions['period']);
        $hits = [];
        $needles = array();

        foreach ($dateOptions['period'] as $key => $date) {
            if ($date->gte($dateHired)) {
                $needle = array_search(Carbon::parse($date)->toDateString(), array_column($arrayData, 'date'));

                if ($key >= $offset && $key <= $limit - 1) {
                    if ($needle === false) {
                        array_push($hits, [
                            "id" => rand(10, 1000),
                            "company_name" => $company->name,
                            "project_name" => 'Stand by',
                            "status" => 'Stand by',
                            "clock_in" => null,
                            "clock_out" => null,
                            "date" => Carbon::parse($date)->toDateString(),
                            "address" => 'Unavailable',
                            "location" => [
                                "street_address" => $company->street_address,
                                "city" => $company->city,
                                "state" => $company->state,
                                "zipcode" => (int) $company->zipcode,
                            ],
                            "total_hours" => 00.0,
                        ]);
                    } else if ($arrayData[$needle]['status'] == 'approved') {
                        array_push($hits, $arrayData[$needle]);
                    }
                }
            }
        }

        return [
            "count" => count($data),
            "hits" => $hits,
            "Actual_Timesheet" => $arrayData,
            "generated_period" => $dateOptions,
        ];
    }

    public function getSchedule($payload)
    {
        $workerId = Auth::user()->id;
        $filters = json_decode($payload->filters);

        $dateFrom = $filters->date->from;
        $dateTo = $filters->date->to;

        $Schedules = ProjectWorkersTimesheet::select(
            'project_workers_timesheet.id',
            'project_workers_timesheet.total_hours',
            'project_workers_timesheet.status',
            'projects.name as project_name',
            'companies.name as company_name',
            'projects.location',
            'projects.clock_in',
            'projects.clock_out',
            'project_workers_timesheet.date',
        )
            ->join('assigned_workers', 'assigned_workers.id', '=', 'project_workers_timesheet.project_worker_id')
            ->join('projects', 'assigned_workers.project_id', '=', 'projects.id')
            ->join('companies', 'companies.id', '=', 'projects.company_id')
            ->where('project_workers_timesheet.worker_id', $workerId)
            ->whereBetween('project_workers_timesheet.date', [$dateFrom, $dateTo])
            ->orWhereIn('project_workers_timesheet.status', ['submitted', 'pending', 'request modification'])
            ->whereNull('project_workers_timesheet.deleted_at')
            ->orderBy('date', 'ASC');

        return $Schedules;
    }

    public function getTimesheetNotification($payload)
    {
        return TimesheetNotification::where('worker_id', Auth::user()->id)->where('is_read', false)->get();
    }

    public function GeneratePeriod($date, $caller)
    {
        $from = null;
        $to = null;

        if ($caller == 'pending') {
            $from = !$date ? Carbon::parse($this->getServerTodayDate()) : $date['from'];
            $to = !$date ? Carbon::now()->add(30, 'days') : $date['to'];
        } else {
            $from = Carbon::now()->subtract(30, 'days');
            $to = Carbon::parse($this->getServerTodayDate());
        }

        $count = Carbon::parse($date ? $date['from'] : $from)->diffInDays(Carbon::parse($date ? $date['to'] : $to));
        $datePeriod = CarbonPeriod::create($date ? $date['from'] : $from, $date ? $date['to'] : $to);

        return [
            'count' => $count,
            'period' => $datePeriod->toArray(),
        ];
    }

    public function saveRenderedHours($payload)
    {
        $updateDetails = [
            'total_hours' => $payload->rendered_hours,
            'status' => 'submitted',
        ];

        return ProjectWorkersTimesheet::where('id', $payload->schedule_id)->update($updateDetails);
    }

    public function toDataArray($data)
    {
        $arr = [];
        for ($x = 0; $x <= count($data) - 1; $x++) {
            array_push($arr, [
                "clock_in" => $data[$x]->clock_in,
                "clock_out" => $data[$x]->clock_out,
                "company_name" => $data[$x]->company_name,
                "date" => $data[$x]->date,
                "id" => $data[$x]->id,
                "location" => json_decode($data[$x]->location),
                "project_name" => $data[$x]->project_name,
                "status" => $data[$x]->status,
                "total_hours" => $data[$x]->total_hours,
            ]);
        }

        return $arr;
    }


    public function todaysSchedule(){
        $today = Carbon::now()->format('Y-m-d');
        $workerID = Auth::user()->id;


        $todaySchedule = ProjectWorkersTimesheet::select(
            'project_workers_timesheet.id',
            'project_workers_timesheet.total_hours',
            'project_workers_timesheet.status',
            'projects.name as project_name',
            'companies.name as company_name',
            'projects.location',
            'projects.clock_in',
            'projects.clock_out',
            'project_workers_timesheet.date',
        )
            ->join('assigned_workers', 'assigned_workers.id', '=', 'project_workers_timesheet.project_worker_id')
            ->join('projects', 'assigned_workers.project_id', '=', 'projects.id')
            ->join('companies', 'companies.id', '=', 'projects.company_id')
        /*  ->where('project_workers_timesheet.status', 'pending') */
            ->where('project_workers_timesheet.worker_id', $workerID)
            ->where('project_workers_timesheet.date', $today)
            ->whereNull('project_workers_timesheet.deleted_at')
            ->first();



        // worker has schedule
        if($todaySchedule){

            $todaySchedule->location = json_decode($todaySchedule->location);
            return $todaySchedule;
        }

        $isBorrowed = WorkerModule::getBorrowerCompany($workerID, Carbon::parse($today)->toDateString());

        // If worker is borrowed and no project data
        if($isBorrowed){
            return [
                "id" => rand(10, 1000),
                "company_name" => $isBorrowed->name,
                "project_name" => 'Stand by',
                "status" => 'Stand by',
                "clock_in" => null,
                "clock_out" => null,
                "date" => Carbon::parse($today)->toDateString(),
                "plain_date" => $today,
                "address" => 'Unavailable',
                "location" => [
                    "street_address" => $isBorrowed->street_address,
                    "city" => $isBorrowed->city,
                    "state" => $isBorrowed->state,
                    "zipcode" => (int) $isBorrowed->zipcode,
                    "report_to" => $isBorrowed->contact_person_name,
                    "tel_no" => $isBorrowed->company_tel,
                ],
                "total_hours" => 00.0,
                "has_project" => false,
            ];
        }else{
            //if worker has no project
            $company = Company::companyInfo($this->getCurrentUser()->company_id);
            return  [
                "id" => rand(10, 1000),
                "company_name" => $company->name,
                "project_name" => 'Stand by',
                "status" => 'Stand by',
                "clock_in" => null,
                "clock_out" => null,
                "date" => Carbon::parse($today)->toDateString(),
                "plain_date" => $today,
                "address" => 'Unavailable',
                "location" => [
                    "street_address" => $company->street_address,
                    "city" => $company->city,
                    "state" => $company->state,
                    "zipcode" => (int) $company->zipcode,
                    "tel_no" => $company->company_tel,
                    "report_to" => $company->contact_person_name,
                ],
                "total_hours" => 00.0,
                "has_project" => false,
            ];
        }
    }   
}
