<?php


namespace App\Services;


use App\LaborReport;
use Carbon\Carbon;
use DateTime;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Ramsey\Uuid\Type\Integer;
use App\Traits\ServiceAppAop;


class LaborReportsCountingRecordService
{
    use ServiceAppAop;
    protected $modelClass=LaborReportsCountingRecord::class;
    public function __construct(LaborReport $laborReport)
    {
        $laborReport::$withoutAppends = false;
    }
    public function userGroupsCount($start, $end)
    {
        $resultByCache = Cache::remember('userGroupsCount_' . $start . '_' . $end, 600, function () use ($start, $end) {
            return LaborReport::query()->selectRaw('user_workgroup_id,count(user_workgroup_id) amount')
                ->with('userWorkgroup', 'laborReportStatus')
                ->whereDate('created_at', '>=', $start)
                ->whereDate('created_at', '<', $end)
                ->groupBy('user_workgroup_id')->get();
        });

        $resultByCache = $resultByCache->filter(function ($item) {
            return $item->amount != 0;
        });

        $result = collect();
        $resultByCache->each(function ($item) use (&$result) {
            $result->push(
                [
                    'value' => $item->amount,
                    'name' => $item->userWorkgroup->name,
                    'id' => $item->userWorkgroup->id,
                ]
            );
        });
        return $result->sortBy('id');
    }

    public function get($start, $end, $unit = '日')
    {
        $resultByCache = $this->getByCache($start, $end, $unit);
        if ($resultByCache['dateList'] == []) {
            return $resultByCache['dataList'];
        } else {
            $this->syncDBToCache($resultByCache['dateList'], $unit);
            return $this->getByCache($start, $end, $unit)['dataList'];
        }
    }

    public function getByCache($start, $end, $unit)
    {
        $dataList = collect();
        $dateList = collect($this->periodDateToArray($start, $end, $unit));
        $result = [];
        foreach ($dateList as $date) {
            $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
            $item = Cache::get($key);
            if ($item) {
                $dataList->push($item);
                $dateList = $dateList->reject(function ($value) use ($date) {
                    return $value == $date;
                });
            }
        }
        $result['dataList'] = $dataList;
        $result['dateList'] = $dateList->toArray();
        return $result;
    }


    /**
     * @param $start
     * @param $end
     * @param string $unit
     * @return array
     */
    private function periodDateToArray($start, $end, $unit = '日')
    {
        $dataArray = [];
        switch ($unit) {
            case '日';
                foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) {
                    $dataArray[] = $item->toDateString();
                }
                break;
            case '月';
                foreach (Carbon::parse($start)->monthsUntil($end, 1)->toArray() as $item) {
                    $dataArray[] = $item->year . '-' . $item->format('m') . '';
                }
                break;
            case '年';
                foreach (Carbon::parse($start)->yearsUntil($end, 1)->toArray() as $item) {
                    $dataArray[] = $item->year.'';
                }
                break;
            default:
                break;
        }
        return $dataArray;
    }

    private function syncDBToCache($dateList, $unit)
    {
        switch ($unit) {
            case '日':
                $query = LaborReport::query()
                    ->selectRaw("DATE_FORMAT(created_at,'%Y-%m-%d') as date_target, count(DISTINCT enter_number ) as counter");
                foreach ($dateList as $startOfWeek) {
                    $query->orWhere(function ($query) use ($startOfWeek) {
                        $query->whereDate('created_at', $startOfWeek);
                    });
                }
                $dataList = $query->groupBy('date_target')->get();
                $dataList->each(function ($item) use ($unit) {
                    $date = $item->date_target;
                    $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
                    Cache::put($key, $item);
                });
                break;
            case '月':
                $query = LaborReport::query()->selectRaw("DATE_FORMAT(created_at,'%Y-%m') as date_target, count(DISTINCT enter_number ) as counter");
                foreach ($dateList as $date) {
                    $query->orWhere(function ($query) use ($date) {
                        $year = Str::of($date)->explode('-')[0];
                        $month = Str::of($date)->explode('-')[1];
                        $query->whereYear('created_at', $year)->whereMonth('created_at', $month);
                    });
                }
                $dataList = $query->groupBy('date_target')->get();
                $dataList->each(function ($item) use ($unit) {
                    $date = $item->date_target;
                    $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
                    Cache::put($key, $item);
                });
                break;
            case '年':
                $query = LaborReport::query()->selectRaw("DATE_FORMAT(created_at,'%Y') as date_target, count(DISTINCT enter_number ) as counter");
                foreach ($dateList as $date) {
                    $query->orWhere(function ($query) use ($date) {
                        $year = Str::of($date)->explode('-')[0];
                        $query->whereYear('created_at', $year)->whereYear('created_at', $year);
                    });
                }
                $dataList = $query->groupBy('date_target')->get();
                $dataList->each(function ($item) use ($unit) {
                    $date = $item->date_target;
                    $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
                    Cache::put($key, $item);
                });
                break;
            default:
                break;
        }
    }
}
