<?php

namespace App\Imports;

use App\Models\DailyStockRecord;
use App\Models\Goods;
use App\Models\GoodsBrand;
use App\Models\GoodsSku;
use App\Models\GoodsType;
use App\Utils\DateTimeUtils;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Facades\Validator;
use App\Utils\ArrayUtils;

class GoodsSkusImport implements ToCollection, SkipsEmptyRows
{
    private $statusMap = [
        '下架' => 0,
        '在售' => 1,
        '预警' => 2,
    ];

    /**
     * @throws ValidationException
     * @throws Exception
     */
    public function collection(Collection $collection)
    {
        unset($collection[0], $collection[1]);
        $collection = $collection->toArray();
        $types = $brands = $goodsCodes = [];
        foreach ($collection as &$row) {
            $row = array_map(static function ($v) {
                return trim($v);
            }, $row);
            $types[] = $row[1];
            $brands[] = $row[2];
            $goodsCodes[] = $row[3];
        }
        unset($row);
        $validator = Validator::make($collection, [
            '*.0' => ['required', 'string', 'max:191'], // 商品名称
            '*.1' => ['required', 'string', 'max:191', 'exists:goods_types,name'], // 分类
            '*.2' => ['string', 'max:191', 'exists:goods_brands,name'], // 品牌
            '*.3' => ['required', 'alpha_dash', 'max:32'], // 商品编码
            '*.4' => ['required', 'string', 'max:191'], // 规格名称
            '*.5' => ['required', 'alpha_dash', 'max:32'], // 规格编码
            '*.6' => ['required', 'string', Rule::in(['下架', '在售', '预警'])],
            '*.7' => ['required', 'max:10'], // 数量
            '*.8' => ['required', 'max:10'], // 成本
        ]);
        if ($validator->fails()) {
            throw new ValidationException($validator);
        }
        $types = GoodsType::query()->whereIn('name', $types)->pluck('id', 'name')->toArray();

        $brands = GoodsBrand::query()->whereIn('name', $brands)->pluck('id', 'name')->toArray();

        $hasGoods = Goods::query()->whereIn('goods_code', $goodsCodes)->pluck('id', 'goods_code')->toArray();

        $newGoods = $skus = [];
        foreach ($collection as $row) {
            $sku = [
                'goods_code' => $row[3],
                'title' => $row[4],
                'sku_code' => $row[5],
                'status' => $this->statusMap[$row[6]],
                'num' => $row[7],
                'cost' => $row[8],
            ];
            // 主商品已存在
            if (isset($hasGoods[$sku['goods_code']])) {
                $sku['goods_id'] = $hasGoods[$sku['goods_code']];
            } else {
                // 新商品
                $newGoods[$sku['goods_code']] = [
                    'title' => $row[0],
                    'type_id' => $types[$row[1]],
                    'brand_id' => $brands[$row[2]],
                    'goods_code' => $sku['goods_code'],
                ];
            }
            $skus[] = $sku;
        }
        DB::beginTransaction();
        try {
            if ($newGoods) {
                $goods = new Goods();
                $goods->batchInsert(array_values($newGoods));
                $hasGoods = Goods::query()
                    ->whereIn('goods_code', array_column($newGoods, 'goods_code'))
                    ->get()
                    ->toArray();
                $hasGoods = ArrayUtils::index($hasGoods, 'goods_code');
                foreach ($skus as &$newGoodsSku) {
                    $newGoodsSku['goods_id'] = $hasGoods[$newGoodsSku['goods_code']]['id'];
                    $newGoodsSku['external_sku_id'] = $newGoodsSku['goods_code'] . '_' . $newGoodsSku['sku_code'];
                    $newGoodsSku['name'] = $hasGoods[$newGoodsSku['goods_code']]['title'] . '_' . $newGoodsSku['title'];
                    unset($newGoodsSku['goods_code']);
                }
                unset($newGoodsSku);
            }
            $goodsSku = new GoodsSku();
            $goodsSku->batchInsert(array_values($skus));
            $goodsIds = Goods::query()->whereIn('goods_code', $goodsCodes)->pluck('id')->toArray();
            $skuIds = GoodsSku::query()->whereIn('goods_id', $goodsIds)->pluck('id')->toArray();
            $newRecords = [];
            $day = DateTimeUtils::getToday();
            foreach ($skuIds as $skuId) {
                $newRecords[] = [
                    'sku_id' => $skuId,
                    'day' => $day,
                ];
            }
            $record = new DailyStockRecord();
            $record->batchInsert($newRecords);
            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();
            // 返回错误
            throw $exception;
        }
    }
}
