<?php

namespace App\Http\Controllers;

use App\Components\AsyncResponse;
use App\OrderPackageCountingRecord;
use App\Owner;
use App\Services\CacheService;
use App\Services\CheckActiveMenuService;
use App\Services\LaborReportsCountingRecordService;
use App\Services\NewOrderCountingRecordService;
use App\Services\RealtimePendingOrdersService;
use App\Services\UserService;
use App\User;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class ControlPanelController extends Controller
{
    use AsyncResponse;

    /**
     * ControlPanelController constructor.
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        $ownerIds = $this->getCountingOwnerIds(null);
        $menus = app(CheckActiveMenuService::class)->activeMenus();
        $owners=Owner::query()->whereIn('id',$ownerIds)->get();
        $warehousesOrders = app(RealtimePendingOrdersService::class)->warehousesOrders();
        return view('control.panel', compact('owners','menus', 'warehousesOrders'));
    }

    public function orderCountingRecordsApi(Request $request)
    {
        /**
         * @var $orderCountingRecordService  NewOrderCountingRecordService
         */
        $orderCountingRecordService = app(NewOrderCountingRecordService::class);
        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
        $ownerIds=$request->owner_ids;
        if (!$ownerIds || in_array('all',$ownerIds)) $ownerIds = $this->getCountingOwnerIds(null);
        $orderCountingRecords = $orderCountingRecordService->orderCountingRecords($start, $end, $request->unit, $ownerIds);
        return compact('orderCountingRecords');
    }

    public function logisticsCountingRecordsApi(Request $request)
    {
        /**
         * @var $orderCountingRecordService  NewOrderCountingRecordService
         */
        $orderCountingRecordService = app(NewOrderCountingRecordService::class);
        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
        $ownerIds=$request->input('owner_ids');
        if (!$ownerIds || in_array('all',$ownerIds)) $ownerIds = $this->getCountingOwnerIds(null);
        $logisticsCountingRecords = $orderCountingRecordService->logisticsCountingRecords($start, $end, $ownerIds);
        return compact('logisticsCountingRecords');
    }

    public function warehouseCountingRecordsApi(Request $request)
    {
        /**
         * @var $orderCountingRecordService  NewOrderCountingRecordService
         */
        $orderCountingRecordService = app(NewOrderCountingRecordService::class);
        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
        $ownerIds = $this->getCountingOwnerIds(null);
        $warehouseCountingRecords = $orderCountingRecordService->warehouseCountingRecords($start, $end, $ownerIds);
        return compact('warehouseCountingRecords');
    }

    public function laborReportsCountingRecordApi(Request $request)
    {
        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
        $unit = $request->unit;
        $laborReportsCountingRecords = $laborReportsCountingRecordService->get($start, $end, $unit);
        return compact('laborReportsCountingRecords');
    }

    public function laborReportsUserGroupsCountApi(Request $request)
    {
        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
        $laborReportsUserGroupsCount = $laborReportsCountingRecordService->userGroupsCount($start, $end);
        return compact('laborReportsUserGroupsCount');
    }


    public function getCountingOwnerIds($ownerIds)
    {

        $user = auth()->user();
        /** @var UserService $userService */
        $userService = app('UserService');
        $permittingOwnerIds = $userService->getPermittingOwnerIds($user);
        if (!$ownerIds) {
            return $permittingOwnerIds;
        }
        return Cache::remember(
            'PermittingOwnerIds' . '_' . auth()->user()->id . '_' . implode('_', $ownerIds),
            600, function () use ($ownerIds, $permittingOwnerIds) {
            /** @var User $user */
            return array_intersect($ownerIds, $permittingOwnerIds);
        });
    }

    /**
     * 获取称重统计数据API
     */
    public function weightApi()
    {
        //转化为Carbon
        $start = Carbon::parse(request("start"));
        $end   = Carbon::parse(request("end"));

        //定义三个数组 空间换时间 避免结果集二次转换
        $title = []; //标题
        $data = []; //核心数据，二维数组
        foreach (CarbonPeriod::create($start,$end) as $date){
            /** @var $date Carbon */
            $str = $date->format("Y-m-d");
            $data[] = $this->getTargetData($str);
            $title[] = $str;
        }

        //大于31天转换为月份显示
        if ($end->diffInDays($start) > 31){
            $title = [];
            $sign = []; //标记是否已被插入
            $dataTemp = []; //临时存储

            foreach ($data as $datum){
                $month = substr($datum["date"],0,7);
                if (!isset($sign[$month])){
                    $dataTemp[] = ["date"=>$month,"total"=>$datum["total"],"count"=>$datum["count"],"value"=>$datum["value"]];
                    $title[] = $month;
                    $sign[$month] = count($dataTemp)-1;
                }else{
                    $dataTemp[$sign[$month]]["total"] += $datum["total"];
                    $dataTemp[$sign[$month]]["count"] += $datum["count"];
                    $dataTemp[$sign[$month]]["value"] = (string)($dataTemp[$sign[$month]]["total"] ? intval(($dataTemp[$sign[$month]]["count"]/$dataTemp[$sign[$month]]["total"])*100) : 0);
                }
            }
            $data = $dataTemp;
        }
        $this->success(["title"=>$title,"data"=>$data]);
    }

    public function exceptionTypeApi(Request $request)
    {
        $ownerIds=$request->owner_ids;
        if (!$ownerIds || in_array('all',$ownerIds)) $ownerIds = $this->getCountingOwnerIds(null);
        $service = app('OrderPackageExceptionTypeCountingRecordService');

        $data = $service->get([
            'start_date' => $request->start,
            'end_date' => $request->end,
            'owner_ids' => $ownerIds,
        ]);
        $this->success(["title"=>'',"data"=>$data]);
    }

    /**
     * 根据指定日期获取目标统计数据
     *
     * @param string $date
     * @return array|null
     */
    private function getTargetData(string $date)
    {
        if ($date == date("Y-m-d")){
            $sql = <<<sql
SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,
SUM(CASE WHEN order_packages.weighed_at IS NOT NULL THEN 1 ELSE 0 END) AS count,
COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=orders.id WHERE orders.wms_status != '订单取消'
AND order_packages.created_at >= '{$date} 00:00:00' GROUP BY date
sql;

            $pack = DB::selectOne(DB::raw($sql));
            if (!$pack)return ["date"=>$date,"total"=>0,"count"=>0,"value"=>0];
            return ["date"=>$pack->date,"total"=>$pack->total,"count"=>$pack->count,"value"=>(string)($pack->total ? intval(($pack->count/$pack->total)*100) : 0)];
        }
        return app(CacheService::class)->getOrExecute("weight.".$date,function ()use($date){
            $count = OrderPackageCountingRecord::query()->where("targeted_at",$date)->first();
            if (!$count)return ["date"=>$date,"total"=>0,"count"=>0,"value"=>0];
            return ["date"=>$count->targeted_at,"total"=>$count->total_count,"count"=>$count->un_weigh_count,"value"=>(string)($count->total_count ? intval(($count->un_weigh_count/$count->total_count)*100) : 0)];
        },config("cache.expirations.forever"));
    }
}
