<?php

namespace App\Modules\Mini\Services;

use App\Base\BaseService;
use App\Models\Goods\Category;
use App\Models\Goods\Goods;
use App\Models\Goods\GoodsCategoryMap;
use App\Models\Goods\GoodsSpecMap;
use App\Models\Goods\Spec;
use App\Models\Goods\SpecAttr;
use App\Models\Setting;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

class PageService extends BaseService
{
    public function banner()
    {
        $banner = Setting::query()->where("type", Setting::TYPE_BANNER)->get();

        return $banner->filter(function (Setting $setting) {
            return $setting->value['is_use'];
        })->sortByDesc(function (Setting $setting) {
            return $setting->value['sort'];
        })->map(function (Setting $setting) {
            return [
                "id" => $setting->id,
                "imageUrl" => $setting->value['imageUrl'],
            ];
        })->values();
    }

    public function categoryTree()
    {
        $categoryS = Category::with("childS")->where("parent_id", 0)->where("index_weight", ">", 0)->orderByDesc("category_weight")->get(["id", "name", "thumb", "parent_id", "level", "weight"]);
        return $categoryS->map(function (Category $category) {
            return [
                "id" => $category->id,
                "name" => $category->name,
                "thumb" => $category->thumb,
                "child" => $this->childTree($category),
            ];
        });
    }

    protected function childTree(Category $category)
    {
        if ($category->childS->isEmpty()) {
            return [];
        }

        return $category->childS->map(function (Category $category) {
            return [
                "id" => $category->id,
                "name" => $category->name,
                "thumb" => $category->thumb,
                "child" => $this->childTree($category),
            ];
        });
    }

    public function hotGoods($num = 10)
    {
        $goods = Goods::where("status", Goods::STATUS_OK)->orderByDesc("view_total")->limit($num)->get();

        return $goods->map(function (Goods $g) {
            return [
                "id" => $g->id,
                "name" => $g->name,
                "thumb" => $g->thumb,
                "view_total" => $g->view_total,
            ];
        });
    }

    public function recommendedGoods($num = 10)
    {
        $goods = Goods::where("status", Goods::STATUS_OK)->orderBy(DB::raw("rand() "))->limit($num)->get();

        return $goods->map(function (Goods $g) {
            return [
                "id" => $g->id,
                "name" => $g->name,
                "thumb" => $g->thumb,
            ];
        });
    }

    public function childCategoryIdArr($id)
    {
        $cids = Category::where("parent_id", $id)->get(["id"])->pluck("id")->toArray();

        $cidss = Category::whereIn("parent_id", $cids)->get(['id'])->pluck("id")->toArray();

        return array_merge($cids, $cidss, [$id]);
    }

    public function filterConfig($params)
    {
        if ($params['type'] == "category") {
            $spec = Spec::with(["attrs"])->orderByDesc("category_weight")->get();
        } else {
            $spec = Spec::with(["attrs"])->orderByDesc("search_weight")->get();
        }

        return $spec->map(function (Spec $model) {
            return [
                "id" => $model->id,
                "name" => $model->name,
                "type" => "attr",
                "child" => $model->attrs->map(function (SpecAttr $attr) {
                    return [
                        "name" => $attr->name,
                    ];
                }),
                "is_custom" => $model->is_custom,
            ];
        });
    }

    public function categoryGoods($params)
    {
        $id = $params['id'];
        $pageSize = Arr::get($params, "page_size");
        $cidArr = $this->childCategoryIdArr($id);

        $gidArr = GoodsCategoryMap::where("category_id", $cidArr)->get(['goods_id'])->pluck("goods_id")->unique()->toArray();
        $attrMap = [];
        if ($attrs = Arr::get($params, "attrs", [])) {
            $attrMap = json_decode($attrs, true);
        }
        $p = Goods::where("status", Goods::STATUS_OK)->when($params['keyword'], function (Builder $query) use ($params) {
            $query->where("name", "like", "%" . $params['keyword'] . "%");
        })->when($attrMap, function (Builder $query) use ($attrMap) {
            $mapQuery = GoodsSpecMap::query();
            foreach ($attrMap as $attr) {
                $mapQuery->orWhere(function (Builder $query) use ($attr) {
                    $query->where("spec_id", $attr['spec_id'])->Where("value", $attr['value']);
                });
            }
            $goodsIdArr = $mapQuery->groupBy("goods_id")->having(DB::raw("count(`goods_id`)"), count($attrMap))->get("goods_id")->pluck("goods_id")->toArray();
            $query->whereIn("id", $goodsIdArr);
        })->orderByDesc("weight")->whereIn("id", $gidArr)->paginate($pageSize);

        return [
            "total" => $p->total(),
            "page_total" => $p->lastPage(),
            "list" => array_map(function (Goods $model) {
                return [
                    "id" => $model->id,
                    "name" => $model->name,
                    "thumb" => $model->thumb,
                    "weight" => $model->weight,
                ];
            }, $p->items()),
        ];

    }

    public function search($params)
    {
        $attrMap = [];
        if ($attrs = Arr::get($params, "attrs", [])) {
            $attrMap = json_decode($attrs, true);
        }
        $pageSize = Arr::get($params, "page_size", 10);
        $p = Goods::where("status", Goods::STATUS_OK)->when($attrMap, function (Builder $query) use ($attrMap) {
            $mapQuery = GoodsSpecMap::query();
            foreach ($attrMap as $attr) {
                $mapQuery->orWhere(function (Builder $query) use ($attr) {
                    $query->where("spec_id", $attr['spec_id'])->Where("value", $attr['value']);
                });
            }
            $goodsIdArr = $mapQuery->groupBy("goods_id")->having(DB::raw("count(`goods_id`)"), count($attrMap))->get("goods_id")->pluck("goods_id")->toArray();
            $query->whereIn("id", $goodsIdArr);

        })->when($params['keyword'], function (Builder $query) use ($params) {
            $query->where("name", "like", "%" . $params['keyword'] . "%");
        })->orderByDesc("weight")->paginate($pageSize);

        return [
            "total" => $p->total(),
            "page_total" => $p->lastPage(),
            "list" => array_map(function (Goods $model) {
                return [
                    "id" => $model->id,
                    "name" => $model->name,
                    "thumb" => $model->thumb,
                    "weight" => $model->weight,
                ];
            }, $p->items()),
            "category" => $this->searchCategory($params['keyword']),
        ];
    }

    private function searchCategory($keyword)
    {
        $c = Category::where("name", "like", "%$keyword%")->orderByDesc("search_weight")->get();

        return $c->map(function (Category $model) {
            return [
                "id" => $model->id,
                "thumb" => $model->thumb,
                "name" => $model->name,
            ];
        });
    }
}