<?php

namespace App\Http\Controllers\Supplier;

use App\Events\BatchStockUpdateEvent;
use App\Http\Controllers\Controller;
use App\Http\Enum\ExcelKeyEnum;
use App\Imports\LossImport;
use App\Models\DailyStockRecord;
use App\Models\Goods;
use App\Models\GoodsSku;
use App\Models\Log;
use App\Models\Log as LogModel;
use App\Models\LossRecords;
use App\Models\Suppliers;
use App\Models\User;
use App\Services\GoodSku\GoodSkuService;
use App\Utils\DateTimeUtils;
use App\Utils\GeneratorUtils;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;

class LossRecordController extends Controller
{
    public function __construct(Request $request)
    {
        $this->log = new LogModel([
            'module' => 'supplier',
            'action' => $request->getMethod(),
            'target_type' => 'loss_record',
        ]);
    }

    public function index(Request $request)
    {
        $builder = LossRecords::query()->filter()->with("goodsSku:name,external_sku_id,title");
        if (!empty($request->start_time) && !empty($request->end_time)) {
            $builder->whereBetween('created_at', [$request->start_time, $request->end_time]);
        }
        if (!empty($request->title)) {
            $builder->whereHas('goodsSku', function ($query) use ($request) {
                $query->where('name', 'like', '%' . $request->title . '%');
            });
        }
        $dailyStockRecord = $builder->orderByDesc("id")->paginate($request->get('per_page'));
        return JsonResource::collection($dailyStockRecord);
    }

    public function store(Request $request)
    {
        //获取所有参数
        $allParams = $request->all();
        //进行校验验证
        $validator = Validator::make($allParams, [
            'external_sku_id' => 'required|string',
            'num' => 'required|integer',
            'reason' => 'sometimes|string',
            'buyer_name' => 'sometimes|string'
        ]);
        if ($validator->fails()) {
            //校验失败返回异常
            $this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
            return response($this->res, $this->res['httpCode']);
        }
        $goodsSku = GoodsSku::query()->where('external_sku_id', "=", $request->external_sku_id)->first();
        if (!empty($goodsSku)) {
            $buyerUserId = User::query()->where("name", $allParams['buyer_name'] ?? '')
                ->pluck("id")->first();
            $today = DateTimeUtils::getToday();
            DB::beginTransaction();
            try {
                //保存記錄
                $lossRecords = new LossRecords();
                $lossRecords->batch_number = GeneratorUtils::generateBatchNumber();
                $lossRecords->external_sku_id = $allParams['external_sku_id'];
                $lossRecords->num = $allParams['num'];
                $lossRecords->cost = $allParams['cost'];
                $lossRecords->date = $allParams['date'] ?? $today;
                $lossRecords->buyer_user_id = $allParams['buyer_user_id'] ?? ($buyerUserId ?? 0);
                $lossRecords->buyer_name = $allParams['buyer_name'] ?? '';
                $lossRecords->reason = $allParams['reason'] ?? '';
                $lossRecords->phenomenon = $v['phenomenon'] ?? '';
                $lossRecords->save();
                $updateIds = GoodSkuService::computeSkuStock($goodsSku->toArray()
                    , ['num' => 0 - $allParams['num'], "cost" => $allParams['cost'], "user_id" => $request->user()->id]);
                DB::commit();
                event(new BatchStockUpdateEvent($updateIds));
            } catch (\Exception $exception) {
                DB::rollBack();
            }

        } else {
            $this->res = [
                'httpCode' => 400,
                'message' => '查询不到sku信息',
                'errorCode' => "ERP001",
                'errorMessage' => '查询不到sku信息',
            ];
        }

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


    public function update($id, Request $request)
    {
        //获取所有参数
        $allParams = $request->all();
        //进行校验验证
        $validator = Validator::make($allParams, [
            'reason' => 'sometimes|string',
            'buyer_name' => 'sometimes|string',
            'buyer_user_id' => 'sometimes|integer'
        ]);
        if ($validator->fails()) {
            //校验失败返回异常
            $this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
            return response($this->res, $this->res['httpCode']);
        }
        $lossRecords = LossRecords::query()->find($id);
        if (!empty($lossRecords)) {
            //更新記錄
            $lossRecords->buyer_name = $allParams['buyer_name'] ?? '';
            $lossRecords->buyer_user_id = $allParams['buyer_user_id'] ?? 0;
            $lossRecords->reason = $allParams['reason'] ?? '';
            $lossRecords->phenomenon = $allParams['phenomenon'] ?? '';
            $lossRecords->save();
        } else {
            $this->res = [
                'httpCode' => 400,
                'message' => '查询不到sku信息',
                'errorCode' => "ERP001",
                'errorMessage' => '查询不到sku信息',
            ];
        }

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

    public function lossBatchStore(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'lossOrders' => 'required|array',
            'lossOrders.*.external_sku_id' => 'required|string',
            'lossOrders.*.num' => 'required|integer',
            'lossOrders.*.reason' => 'sometimes|string',
            'lossOrders.*.buyer_name' => 'sometimes|string',//采购商
            'lossOrders.*.phenomenon' => 'sometimes|string',
            'lossOrders.*.date' => 'sometimes|date_format:Y-m-d'
        ]);
        //参数校验
        if ($validator->fails()) {
            $this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
            return response($this->res, $this->res['httpCode']);
        }
        $lossOrders = $request->input('lossOrders') ?? [];
        $externalSkuIds = collect($lossOrders)->pluck("external_sku_id")->toArray();
        $goodsSku = GoodsSku::query()->whereIn('external_sku_id', $externalSkuIds)->get();
        if ($goodsSku->pluck("external_sku_id")->diff($externalSkuIds)->isNotEmpty()) {
            $content = implode(',', $goodsSku->pluck("external_sku_id")->diff($externalSkuIds)->toArray());
            $content .= "以上sku编码数据库中不存在";
            return response($content, $this->res['httpCode']);
        }
        $goodsSkuMap = $goodsSku->pluck(null, 'external_sku_id')->toArray();
        $allUpdateIds = [];
        $batchNumber = GeneratorUtils::generateBatchNumber();
        $today = DateTimeUtils::getToday();
        //开始保存数据
        foreach ($lossOrders as $v) {
            DB::beginTransaction();
            try {
                $goodsSkuItem = $goodsSkuMap[$v['external_sku_id']];
                //保存記錄
                $lossRecords = new LossRecords();
                $lossRecords->batch_number = $batchNumber;
                $lossRecords->external_sku_id = $v['external_sku_id'];
                $lossRecords->num = $v['num'];
                $lossRecords->cost = $v['cost'];
                $lossRecords->date = $v['date'] ?? $today;
                $lossRecords->buyer_user_id = $v['buyer_user_id'] ?? 0;
                $lossRecords->buyer_name = $v['buyer_name'] ?? '';
                $lossRecords->reason = $v['reason'] ?? '';
                $lossRecords->phenomenon = $v['phenomenon'] ?? '';
                $lossRecords->save();

                $updateIds = GoodSkuService::computeSkuStock($goodsSkuItem
                    , ['num' => 0 - $v['num'], "cost" => $v['cost'], "user_id" => $request->user()->id]);
                DB::commit();
                $allUpdateIds = array_merge($allUpdateIds, $updateIds);
            } catch (\Exception $exception) {
                DB::rollBack();
            }
        }

        event(new BatchStockUpdateEvent(collect($allUpdateIds)->unique()->toArray()));
        return response($this->res, $this->res['httpCode']);
    }


    /**
     * 报损单单后台批量导入
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|void
     */
    public function lossImport(Request $request)
    {
        if (!$request->hasFile(ExcelKeyEnum::LOSS_KEY)) {
            $this->res = [
                'httpCode' => 404,
                'errorCode' => 404404,
                'errorMessage' => 'not found loss file',
            ];
        }
        try {
            $import = new LossImport();
            $path = $request->file(ExcelKeyEnum::LOSS_KEY);
            Excel::import($import, $path);
            $this->addLog(0, 'import', ExcelKeyEnum::LOSS_KEY);
        } catch (ValidationException $exception) {
            $this->setValidatorFailResponse($exception->validator->getMessageBag()->getMessages());
        }

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

}
