<?php

namespace App\Exports;

use App\Http\Enum\TargetTypeEnum;
use App\Models\DailyStockRecord;
use App\Models\Goods;
use App\Models\Log;
use App\Models\PurchaseRecords;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use App\Models\GoodsSku;
use Illuminate\Support\Collection;

class GoodsSkusExport implements FromCollection, ShouldAutoSize
{
    private $data;
    private $type;

    public function __construct($type)
    {
        $this->type = $type;
        $this->data = $this->createData();
    }

    /**
     * @return \Illuminate\Support\Collection
     */
    public function collection()
    {
        return new Collection($this->data);
    }

    private function createData()
    {
        $headTitle = [
            '商品编码',
            '商品名称',
            '在售库存',
            "剩余库存",
            '创建时间',
        ];
        $map = [
            'cost' => ['当前成本', '更新前成本', "更新后成本"],
            'inventory' => ['当前库存', '盘点数', '采购总数'],
        ];
        $headTitle = array_merge($headTitle, $map[$this->type] ?? []);
        if ('cost' === $this->type) {
            $update = $this->getChangeCostLogs();
        }
        if ('inventory' === $this->type) {
            $update = $this->getInventoryRecord();
        }
        if ($this->type === "goods_sku" || $this->type === "goods_combination") {
            $builder = GoodsSku::query();
            if (request()->get('type_id')) {
                $goodsIds = Goods::query()->filter()->pluck('id')->toArray();
                $builder->whereIn('goods_id', $goodsIds);
            }
            if (request()->get('goods_title')) {
                $builder->where('name', 'like', '%' . request()->get('goods_title') . '%');
            }
            if ($this->type === "goods_combination") {
                $builder->where('is_combination', 1);
            } else {
                $builder->where('is_combination', 0);
            }
            $data = $builder->filter()->orderByDesc('id')->get()->toArray();
        } else {
            $ids = array_keys($update);
            if (empty($ids)) {
                return [$headTitle];
            }
            $model = GoodsSku::query()
                ->when($ids, function ($query, $ids) {
                    return $query->whereIn('id', $ids);
                })
                ->with(['goods' => function ($query) {
                    $query->with(['type:id,name', 'brand:id,name'])
                        ->orderBy('type_id')
                        ->orderBy('brand_id');
                }]);
            $data = $model->get()->toArray();
            if (empty($data)) {
                return [$headTitle];
            }
        }

        $bodyData = [];
        foreach ($data as $item) {
            $arr[0] = $item['external_sku_id'];
            $arr[1] = $item['name'];
            $arr[2] = $item['sale_stock'] ?? '0';
            $arr[3] = $item['stock'] ?? '0';
            $arr[4] = $item['created_at'];
            if ('cost' === $this->type) {
                $arr[5] = (string)$item['cost'];
                $arr[6] = (string)$update[$item['id']]['before_update'];
                $arr[7] = (string)$update[$item['id']]['after_update'];
            }
            if ('inventory' === $this->type) {
                $arr[5] = (string)$item['stock'];
                $arr[6] = (string)$update[$item['id']]['inventory'];
                $arr[7] = (string)$update[$item['id']]['arrived_today_num'];
            }
            $bodyData[] = $arr;
        }
        unset($arr);
        return [$headTitle, $bodyData];
    }

    private function getChangeCostLogs()
    {
        $day = DateTimeUtils::getToday();
        $logs = Log::query()
            ->select(['target_id', 'before_update', 'after_update'])
            ->where('target_type', TargetTypeEnum::PURCHASE)
            ->where('target_field', 'stock')
            ->where('created_at', '>', $day)
            ->get();

        $update = [];
        foreach ($logs as $log) {
            if (!isset($update[$log['target_id']])) {
                $beforeData = json_decode($log['before_update'], true);
                if (!empty($beforeData['cost'])) {
                    $update[$log['target_id']]['before_update'] = $beforeData['cost'];
                }

            }
            $afterData = json_decode($log['after_update'], true);
            if (!empty($afterData['cost']) && $afterData['cost'] != $beforeData['cost']) {
                $update[$log['target_id']]['after_update'] = $afterData['cost'];
            }
        }

        return $update;
    }

    private function getInventoryRecord()
    {
        $day = date('Y-m-d', strtotime('-1 day'));
        $records = DailyStockRecord::query()
            ->select(['sku_id', 'inventory', 'arrived_today_num'])
            ->where('day', $day)
            ->where(function ($query) {
                $query->where('arrived_today_num', '<>', 0)
                    ->orWhere('inventory', '<>', 0);
            })
            ->get()
            ->toArray();

        return ArrayUtils::index($records, 'sku_id');
    }
}
