<?php

namespace App\Console\Commands;

use App\Models\BusinessOrder;
use App\Models\BusinessOrderItem;
use App\Models\GoodsSku;
use App\Utils\ArrayUtils;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use App\Models\DailySalesReport as DailySalesReportModel;

class DailySalesReport extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'daily:report:sales {S}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '每日销量数据记录';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $s = $this->argument('S');
        $map = [
            'S1' => [
                'startTime' => date('Y-m-d 11:00:00'),
                'endTime' => date('Y-m-d 12:00:00'),
            ],
            'S2' => [
                'startTime' => date('Y-m-d 11:00:00'),
                'endTime' => date('Y-m-d 13:30:00'),
            ],
            'S3' => [
                'startTime' => date('Y-m-d 11:00:00'),
                'endTime' => date('Y-m-d 15:00:00'),
            ],
            'S4' => [
                'startTime' => date('Y-m-d 15:00:00'),
                'endTime' => date('Y-m-d 16:00:00'),

            ],
            'S5' => [
                'startTime' => date('Y-m-d 11:00:00'),
                'endTime' => date('Y-m-d 17:30:00'),
            ],
            'S6' => [
                'startTime' => date('Y-m-d 11:00:00'),
                'endTime' => date('Y-m-d 20:00:00'),
            ],
            'S7' => [
                'startTime' => Carbon::yesterday()->format('Y-m-d 11:00:00'),
                'endTime' => date('Y-m-d 09:30:00'),
            ],
        ];
        if (!isset($map[$s])) {
            return;
        }
        $startTime = $map[$s]['startTime'];
        $endTime = $map[$s]['endTime'];

        $businessOrderIds = BusinessOrder::query()
            ->where('confirm_at', '>=', Carbon::parse($startTime)->getPreciseTimestamp(3))
            ->where('confirm_at', '<=', Carbon::parse($endTime)->getPreciseTimestamp(3))
            ->pluck('id');
        $businessOrderIds = $businessOrderIds->chunk(200);
        $fields = implode(',', [
            'external_sku_id',
            'SUM(already_cancel_number) as total_already_cancel_number',
            'SUM(goods_number) as total_goods_number',
        ]);

        $data = [];
        foreach ($businessOrderIds as $ids) {
            $businessOrderItems = BusinessOrderItem::query()
                ->select(DB::raw($fields))
                ->whereIn('business_order_id', $ids)
                ->where('external_sku_id', '<>', '')
                ->groupBy('external_sku_id')
                ->get();
            if ($businessOrderItems->isEmpty()) {
                continue;
            }
            foreach ($businessOrderItems as $businessOrderItem) {
                $arr = explode('_', $businessOrderItem['external_sku_id']);
                if (2 !== count($arr)) {
                    continue;
                }
                if (!isset($data[$businessOrderItem['external_sku_id']])) {
                    $data[$businessOrderItem['external_sku_id']] = [
                        'total_already_cancel_number' => 0,
                        'total_goods_number' => 0,
                    ];
                }
                $data[$businessOrderItem['external_sku_id']]['total_already_cancel_number'] += $businessOrderItem['total_already_cancel_number'];
                $data[$businessOrderItem['external_sku_id']]['total_goods_number'] += $businessOrderItem['total_goods_number'];
            }
        }

        $date = Carbon::parse($startTime)->format('Y-m-d');
        $goodsSkus = GoodsSku::query()
            ->select(['goods_id', 'external_sku_id', 'name', 'id', 'goal_rate'])
            ->with(['daily' => function ($query) use ($date) {
                $query->where('day', $date);
            }])
            ->whereIn('external_sku_id', array_keys($data))
            ->get();
        $goodsSkus = ArrayUtils::index($goodsSkus->toArray(), 'external_sku_id');
        foreach ($data as $externalSkuId => $datum) {
            if (!isset($goodsSkus[$externalSkuId])) {
                continue;
            }
            $dailySalesReport = DailySalesReportModel::query()
                ->where('date', $date)
                ->where('external_sku_id', $externalSkuId)
                ->first();
            $sVal = $datum['total_goods_number'] - $datum['total_already_cancel_number'];
            $sRate = $s . '_rate';
            $stock = $goodsSkus[$externalSkuId]['daily']['inventory'] + $goodsSkus[$externalSkuId]['daily']['arrived_today_num'];
            $sRateVal = $stock ? bcdiv($sVal, $stock, 4) : 0;
            if (is_null($dailySalesReport)) {
                DailySalesReportModel::query()->updateOrCreate([
                    'date' => $date,
                    'external_sku_id' => $externalSkuId,
                ], [
                    'goods_id' => $goodsSkus[$externalSkuId]['goods_id'],
                    'goods_sku_id' => $goodsSkus[$externalSkuId]['id'],
                    'name' => $goodsSkus[$externalSkuId]['name'],
                    'inventory' => $goodsSkus[$externalSkuId]['daily']['inventory'],
                    'arrived_today_num' => $goodsSkus[$externalSkuId]['daily']['arrived_today_num'],
                    'sales_num' => $sVal,
                    'loss_num' => $goodsSkus[$externalSkuId]['daily']['loss_num'],
                    $s => $sVal,
                    $sRate => $sRateVal,
                    'already_cancel_number' => $datum['total_already_cancel_number'],
                ]);
            } else {
                $num = 0;
                foreach ($map as $key => $val) {
                    if ($key !== $s) {
                        $num += $dailySalesReport->$key;
                    }
                }
                $dailySalesReport->update([
                    'inventory' => $goodsSkus[$externalSkuId]['daily']['inventory'],
                    'arrived_today_num' => $goodsSkus[$externalSkuId]['daily']['arrived_today_num'],
                    'sales_num' => $num + $sVal,
                    'loss_num' => $goodsSkus[$externalSkuId]['daily']['loss_num'],
                    $s => $sVal,
                    $sRate => $sRateVal,
                    'already_cancel_number' => $datum['total_already_cancel_number'],
                    'goal_rate' => $goodsSkus[$externalSkuId]['goal_rate'],
                ]);
            }
        }
    }
}
