<?php

namespace App\Http\Controllers\Goods;

use App\Http\Controllers\Controller;
use App\Http\Resources\GoodsSkuResource;
use App\Imports\CombinationGoodsImport;
use App\Models\BusinessOrderItem;
use App\Models\CombinationGood;
use App\Models\DeveloperConfig;
use App\Models\Goods;
use App\Models\GoodsSku;
use App\Utils\GeneratorUtils;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;

class GoodsCombinationController extends Controller
{
    public function index(Request $request)
    {
        // ToDo
        $sortField = $request->input('sort_field', 'id');//stock sale_stock  order_goods_num
        $sortValue = $request->input('sort_value', 'desc');
        $fields = implode(',', [
            'shop_id',
            'external_sku_id',
            'SUM(goods_number) - SUM(already_cancel_number) as number',
        ]);
        $orderRestTime = DeveloperConfig::query()
            ->where('key', DeveloperConfig::$ORDER_RESET_TIME)
            ->value('value');
        if (is_null($orderRestTime)) {
            $orderRestTime = date('Y-m-d 07:00:00');
        }

        $businessOrderItems = BusinessOrderItem::query()
            ->select(DB::raw($fields))
            ->with([
                'shop:id,name',
                'goodsSku:id,external_sku_id,is_combination',
                'goodsSku.combinationGoods:id,goods_sku_id,item_id,item_num'
            ])
            ->where('created_at', '>', $orderRestTime)
            ->where('external_sku_id', '<>', '')
            ->groupBy(['shop_id', 'external_sku_id'])
            ->orderByDesc('number')
            ->get()
            ->toArray();
        $ids = $externals = [];
        foreach ($businessOrderItems as $businessOrderItem) {
            if (is_null($businessOrderItem['goods_sku'])) {
                continue;
            }
            $id = $businessOrderItem['goods_sku']['id'];
            if (isset($ids[$id])) {
                $ids[$id] += (int)$businessOrderItem['number'];
            } else {
                $ids[$id] = (int)$businessOrderItem['number'];
            }

            $externals[$id][] = $businessOrderItem;
        }
        arsort($ids);

        //  可通过子商品查找主商品
        $goodsSkusBuilder = GoodsSku::query()
            ->with([
                'combinationGoods:id,goods_sku_id,item_id,item_num',
                'combinationGoods.goodsSkuItem:id,name,goods_id,title,stock,sale_stock,external_sku_id,updated_at,yesterday_num,reference_price,status',
                'combinationGoods.goodsSkuItem.goods:id,title,img_url',
            ])
            ->where('is_combination', 1)
            ->filter();
        if ($sortField == "order_goods_num") {
            $finalIds = [];
            asort($ids);
            foreach ($ids as $id => $number) {
                $finalIds[] = $id;
            }

            $idField = implode(',', $finalIds);
            $goodsSkusBuilder->orderByRaw("FIELD(id,{$idField}) {$sortValue}");
        } else {
            $goodsSkusBuilder->orderBy($sortField, $sortValue);
        }
        $skus = $goodsSkusBuilder
            ->paginate($request->get('per_page'));
        foreach ($skus as &$item) {
            $items = [];
            if (isset($externals[$item['id']])) {
                $item['order_detail'] = $externals[$item['id']];
                $item['order_goods_num'] = $ids[$item['id']];
            } else {
                $item['order_detail'] = [];
                $item['order_goods_num'] = 0;
            }

            $number = BusinessOrderItem::query()
                ->where('external_sku_id', $item['external_sku_id'])
                ->sum('goods_number');
            $cancelNumber = BusinessOrderItem::query()
                ->where('external_sku_id', $item['external_sku_id'])
                ->sum('already_cancel_number');
            $item['total_orders_num'] = $number - $cancelNumber;
            foreach ($item['combinationGoods'] as $combinationItem) {
                $title = !empty($combinationItem['goodsSkuItem']['name']) ? $combinationItem['goodsSkuItem']['name'] :
                    (!empty($combinationItem['goodsSkuItem']['goods']) ? $combinationItem['goodsSkuItem']['goods']['title']
                        . " " . $combinationItem['goodsSkuItem']['title'] : $combinationItem['goodsSkuItem']['title']);
                $items[] = [
                    'cost' => 0,
                    'external_sku_id' => $combinationItem['goodsSkuItem']['external_sku_id'],
                    'goods_id' => $combinationItem['goodsSkuItem']['goods_id'],
                    'id' => $combinationItem['id'],
                    'is_combination' => 0,
                    'num' => $combinationItem['item_num'],
                    'reference_price' => $combinationItem['goodsSkuItem']['reference_price'],
                    'status' => $combinationItem['goodsSkuItem']['status'],
                    'stock' => $combinationItem['goodsSkuItem']['stock'],
                    'sale_stock' => $combinationItem['goodsSkuItem']['sale_stock'],
                    'thumb_url' => null,
                    'img_url' => null,//图片暂时去掉
                    'title' => $title,
                    'updated_at' => $combinationItem['goodsSkuItem']['updated_at'],
                    'yesterday_num' => $combinationItem['goodsSkuItem']['yesterday_num'],
                    'order_goods_num' => '请在商品列表查看',
                    'order_detail' => [],
                    'total_orders_num' => '不显示',
                ];
            }
            $item['children'] = $items;
            unset($item['combinationGoods']);
        }
        $rolesName = $request->user()->getRoleNames()->toArray();
        $data = ["manage" => ["is_admin" => in_array($rolesName[0]
            , ["运营", "超级管理员", "管理员", "系统管理员", "店铺运营"]) ? 1 : 0]];

        return GoodsSkuResource::collection($skus)->additional($data);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required',
            'external_sku_id' => 'sometimes',
            'combination_goods.*' => 'required',
            'combination_goods.*.item_id' => 'required',
            'combination_goods.*.item_num' => 'required|gt:0',
        ]);
        if ($validator->fails()) {
            $this->setValidatorFailResponse($validator->getMessageBag()->getMessages());

            return response($this->res, $this->res['httpCode']);
        }
        $externalSkuId = $request->input('external_sku_id') ??
            GeneratorUtils::generateCombinationGoodNumber($request->combination_goods);
        $hasCodeSku = GoodsSku::query()->where("external_sku_id", $externalSkuId)->first();
        if (!empty($hasCodeSku) && $hasCodeSku->id != $request->input('id',0)) {
            throw new \Exception("该组合商品编码已存在");
        }
        DB::beginTransaction();
        try {
            $combinationGoods = $request->input('combination_goods');
            $itemIds = array_column($combinationGoods, 'item_id');
            $skus = GoodsSku::query()
                ->whereIn('id', $itemIds)
                ->get()
                ->pluck(null, 'id')
                ->toArray();
            $stock = [];
            $saleStock = [];
            foreach ($combinationGoods as $item) {
                if (!empty($skus[$item['item_id']])) {
                    $stock[] = (int)($skus[$item['item_id']]['stock'] / $item['item_num']);
                    $saleStock[] = (int)($skus[$item['item_id']]['sale_stock'] / $item['item_num']);
                }
            }
            $stock = min($stock);
            $saleStock = min($saleStock);

            $status = $saleStock ? (5 < $saleStock ? 1 : 2) : 0;
            if ($id = $request->input('id')) {
                $sku = GoodsSku::query()->findOrFail($id);
            } else {
                $sku = new GoodsSku();
                $sku->goods_id = 0;
                $sku->is_combination = 1;
            }


            $sku->status = $status;
            $sku->title = $request->input('title');
            $sku->name = $request->input('title');
            $sku->sku_code = $externalSkuId;
            $sku->external_sku_id = $externalSkuId;
            $sku->stock = $stock;
            $sku->sale_stock = $saleStock;
            $sku->save();
            CombinationGood::query()
                ->where('goods_sku_id', $sku->id)
                ->delete();
            foreach ($combinationGoods as $item) {
                CombinationGood::query()->create(['goods_sku_id' => $sku->id, 'item_id' => $item['item_id'], 'item_num' => $item['item_num']]);
            }
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            $this->res = [
                'httpCode' => 400,
                'errorCode' => 400500,
                'errorMessage' => $exception->getMessage(),
            ];
        }

        return response($this->res, $this->res['httpCode']);
    }

    public function show(Request $request, $id)
    {
        $sku = GoodsSku::query()
            ->with([
                'combinationGoods:id,goods_sku_id,item_id,item_num',
                'combinationGoods.goodsSkuItem:id,title,goods_id',
                'combinationGoods.goodsSkuItem.goods:id,title',
            ])
            ->findOrFail($id);
        $items = [];
        foreach ($sku['combinationGoods'] as $item) {
            $items[] = [
                'id' => $item['goodsSkuItem']['id'],
                'title' => $item['goodsSkuItem']['goods']['title'] . $item['goodsSkuItem']['title'],
            ];
        }
        $sku['skus'] = $items;

        return new GoodsSkuResource($sku);
    }

    public function destroy(Request $request, $id)
    {

    }

    public function goodsSkus(Request $request, $title)
    {
        $skus = GoodsSku::query()
            ->where('name', 'like', '%' . $title . '%')
            ->where('is_combination', 0)
            ->with('goods:id,title')
            ->get(['id', 'title', 'goods_id', "name"]);
        foreach ($skus as &$sku) {
            if (!empty($sku['name'])) {
                $sku['title'] = $sku['name'];
            } else {
                $sku['title'] = ($sku['goods']['title'] ?? "") . $sku['title'];
            }
        }

        return GoodsSkuResource::collection($skus);
    }

    public function import(Request $request)
    {
        if (!$request->hasFile('combinationGoods')) {
            $this->res = [
                'httpCode' => 404,
                'errorCode' => 404404,
                'errorMessage' => 'not found file',
            ];
        }
        try {
            $import = new CombinationGoodsImport();
            $path = $request->file('combinationGoods');
            Excel::import($import, $path);
        } catch (ValidationException $exception) {
            $this->setValidatorFailResponse($exception->validator->getMessageBag()->getMessages());
        }

        return response($this->res, $this->res['httpCode']);
    }
}
