<?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\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)->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)
    {
        $spec = Spec::whereIsCustom(0)->get();

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

    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();
        $attrIdArr = [];
        if ($attrs = Arr::get($params, "attrs", [])) {
            $attrIdArr = 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($attrIdArr, function (Builder $query) use ($attrIdArr) {
            $d = SpecAttr::whereIn("id", $attrIdArr)->groupBy("spec_id")->get(['spec_id']);
            $specIdArr = $d->pluck("spec_id")->toArray();
            foreach ($specIdArr as $specId) {
                $query->whereJsonContains("spec", $specId);
            }
        })->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)
    {
        $attrId = [];
        if ($attrs = Arr::get($params, "attrs", [])) {
            $attrId = json_decode($attrs, true);
        }
        $pageSize = Arr::get($params, "page_size", 10);
        $p = Goods::where("status", Goods::STATUS_OK)->when($attrId, function (Builder $query) use ($attrId) {
            $d = SpecAttr::whereIn("id", $attrId)->groupBy("spec_id")->get(['spec_id']);
            $specIdArr = $d->pluck("spec_id")->toArray();
            foreach ($specIdArr as $specId) {
                $query->whereJsonContains("spec", $specId);
            }
        })->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%")->get();

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