<?php
declare (strict_types = 1);

namespace app\index\controller;

use app\index\model\ProductAttrModel;
use app\index\model\ProductCategoryModel;
use app\index\model\ProductInquiryModel;
use app\index\model\ProductModel;
use app\index\model\ProductParamsModel;
use app\index\model\ProductPurchaseLinkModel;
use app\index\model\ProductRelatedModel;
use app\index\model\ProductSkuAttrModel;
use app\index\model\ProductSkuModel;
use app\index\model\SysBannerModel;
use app\index\model\SysBannerProdCateMappingModel;
use app\index\validate\ProductInquiryValidate;
use think\facade\View;
use think\helper\Arr;

/**
 * 产品控制器
 */
class Product extends Common
{
    // 获取分类页的banner图焦点横幅
    private function getCategoryBanner($category_id)
    {
        $focus_image = [];
        // 获取产品分类页焦点横幅
        $banner = SysBannerModel::with(['items' => function($query) use($category_id) {
                $query->withoutField([
                        'status',
                        'created_at',
                        'updated_at',
                        'deleted_at'
                    ])
                    ->whereExists(function($q) use($category_id) {
                        $r = $q->getModel()->getTable();
                        $m = new SysBannerProdCateMappingModel;
                        $q->model($m)->name($m->getName())
                            ->where("banner_item_id = $r.id")
                            ->where('product_category_id' , '=', $category_id);
                    })
                    ->where('status', '=', 1)
                    ->order(['sort' => 'asc', 'id' => 'desc']);
            }])
            ->atPlatform(request()->from)
            ->uniqueLabel(['BANNER_6808abd813d78'])
            ->language($this->lang_id)
            ->enabled(true)
            ->select();
        if (!$banner->isEmpty()) {
            $banner_map = [];
            foreach ($banner as $v) {
                $banner_map[$v->unique_label] = $v;
            }
            $focus_image = data_get($banner_map, 'BANNER_6808abd813d78')?->items->toArray();
        }
        return $focus_image;
    }
    // 产品分类 - 查看顶层分类
    public function category()
    {
        // 参数
        $param = request()->param(['id']);

        // 获取产品分类页焦点横幅
        View::assign('focus_image', $this->getCategoryBanner($param['id']));

        // 获取分类及产品信息
        $categorys_data = ProductCategoryModel::field(['id', 'pid', 'name', 'path', 'level'])
            ->language($this->lang_id)
            ->displayed(true)
            ->children($param['id'])
            ->order(['pid' => 'asc', 'sort' => 'asc', 'id' => 'desc'])
            ->select()
            ->toArray();

        $list = [];
        if (!empty($categorys_data)) {
            // 分组分类
            $list = array_filter($categorys_data, fn($it) => $it['level'] == 2);
            foreach ($list as &$it) {
                $it['children'] = array_column(array_filter($categorys_data, fn($v) => in_array($it['id'], explode(',', $v['path']))), 'id');
            }
            unset($it);

            // 获取分类下的产品信息
            if (!empty($list)) {
                $product_model = new ProductModel;
                $sql           = $product_model->field([
                        'id',
                        'category_id',
                        'spu',
                        'name',
                        'cover_image',
                        'is_new',
                        '(' . $list[0]['id'] . ')' => 'group_mark'
                    ])
                    ->byCategory(data_get($list[0], 'children'))
                    ->language($this->lang_id)
                    ->enabled(true)
                    ->onSale(true)
                    ->onShelves(true)
                    ->append(['p' => $list[0]['id']])
                    ->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
                    ->limit(5)
                    ->buildSql();
                $query = \think\facade\Db::table("($sql) as a");
                foreach ($list as $it) {
                    $query = $query->union(function($query) use($product_model, $it) {
                        $query->model($product_model)
                        ->name($product_model->getName())
                        ->field([
                            'id',
                            'category_id',
                            'spu',
                            'name',
                            'cover_image',
                            'is_new',
                            '(' . $it['id'] . ')' => 'group_mark'
                        ])
                        ->byCategory($it['children'])
                        ->language($this->lang_id)
                        ->enabled(true)
                        ->onSale(true)
                        ->onShelves(true)
                        ->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
                        ->limit(5);
                    });
                }
                $pros = $query->select();
                if (!empty($pros)) {
                    $pros_map = [];
                    foreach ($pros as $pro) {
                        $pros_map[$pro['group_mark']][] = $pro;
                    }
                    foreach ($list as $k => &$it) {
                        unset($it['children']);
                        if (!isset($pros_map[$it['id']])) {
                            unset($list[$k]);
                            continue;
                        }
                        $it['products'] = $pros_map[$it['id']];
                    }
                    unset($it);
                }
            }
        }
        View::assign('list', $list);

        return View::fetch('category');
    }
    // 产品分类 - 查看子类
    public function subcategory()
    {
        // 参数
        $param = request()->param(['id']);

        // 获取产品分类页焦点横幅
        View::assign('focus_image', $this->getCategoryBanner($param['id']));

        // 获取分类及产品信息
        $categorys_data = ProductCategoryModel::field(['id', 'name', 'level'])
            ->language($this->lang_id)
            ->displayed(true)
            ->child($param['id'], true)
            ->order(['sort' => 'asc', 'id' => 'desc'])
            ->select();

        if (!$categorys_data->isEmpty()) {
            if ($categorys_data->count() > 1) {
                // 当分类数不只一个时，当前分类下有子分类，移除当前分类，只输出子分类
                $categorys_data = $categorys_data->filter(function($item) use($param) {
                    return $item->id != $param['id'];
                });
            }
            $categorys_data = $categorys_data->toArray();

            $products  = ProductModel::field([
                    'id',
                    'category_id',
                    'spu',
                    'name',
                    'short_name',
                    'cover_image',
                    'desc'
                ])
                ->byCategory(array_column($categorys_data, 'id'))
                ->language($this->lang_id)
                ->enabled(true)
                ->onSale(true)
                ->onShelves(true)
                ->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
                ->select();
            if (!$products->isEmpty()) {
                // 获取sku信息
                $skus_map  = [];
                $color_map = [];
                $skus      = ProductSkuModel::withoutField(['sort', 'created_at', 'updated_at'])
                    ->byProductId(Arr::pluck($products, 'id'))
                    ->order(['sort' => 'asc', 'id' => 'asc'])
                    ->select();
                if (!$skus->isEmpty()) {
                    // 获取产品sku属性信息
                    $sku_attrs_map = [];
                    $sku_attrs     = ProductSkuAttrModel::bySkuId(array_unique(Arr::pluck($skus, 'id')))->select()->toArray();
                    if (!empty($sku_attrs)) {
                        // 获取属性名称
                        $attrs = ProductAttrModel::bypks(array_unique(Arr::pluck($sku_attrs, 'attr_id')))->column(['attr_name'], 'id');
                        // 获取属性名称
                        foreach ($sku_attrs as $v) {
                            $sku_attrs_map[$v['sku_id']][] = [
                                'sku_id'     => $v['sku_id'],
                                'attr_id'    => $v['attr_id'],
                                'attr_name'  => $attrs[$v['attr_id']]?? '',
                                'attr_value' => $v['attr_value']
                            ];
                        }
                    }
                    // sku匹配属性
                    foreach ($skus as $v) {
                        // 找到相应产品的sku图片信息
                        $skus_map[$v['product_id']][] = [
                            'id'         => $v['id'],
                            'sku'        => $v['sku'],
                            'main_image' => $v['main_image'],
                        ];
                        // 找到相应产品的sku产色属性信息
                        $attr = $sku_attrs_map[$v['id']]?? [];
                        if (!empty($attr)) {
                            foreach ($attr as $at) {
                                if (in_array($at['attr_name'], ['颜色', 'Color'])) {
                                    $color_map[$v['product_id']][] = $at;
                                }
                            }
                        }
                    }
                }

                // 按分类分组产品
                $products_map = [];
                foreach ($products as $v) {
                    $products_map[$v['category_id']][] = [
                        'id'          => $v['id'],
                        'spu'         => $v['spu'],
                        'name'        => $v['name'],
                        'short_name'  => $v['short_name'],
                        'cover_image' => $v['cover_image'],
                        'desc'        => $v['desc'],
                        'sku'         => $skus_map[$v['id']]?? [],
                        'colors'      => $color_map[$v['id']]?? []
                    ];
                }
                foreach ($categorys_data as $k => $v) {
                    if (!isset($products_map[$v['id']])) {
                        unset($categorys_data[$k]);
                        continue;
                    }
                    $categorys_data[$k]['products'] = $products_map[$v['id']];
                }
            }
        }
        View::assign('categorys_data', $categorys_data);

        return View::fetch('subcategory');
    }


    /**
     * 单纯分类页
     */
    public function classify()
    {
        $pid    = request()->param('id/d', 0);

        // 获取当前选中的父分类
        $parent = ProductCategoryModel::field(['id', 'name'])->find($pid);
        View::assign('parent', $parent);

        // 获取分类及产品信息
        $categorys = ProductCategoryModel::field(['id', 'pid', 'name', 'path', 'level'])
            ->language($this->lang_id)
            ->displayed(true)
            ->children($pid)
            ->order(['pid' => 'asc', 'sort' => 'asc', 'id' => 'desc'])
            ->select()
            ->toArray();

        // 组装第三级分类所属产品数据
        $lv3_id_arr = array_column(array_filter($categorys, fn($item)=> $item['level'] === 3), 'id');
        $products   = ProductModel::field([
                'id',
                'category_id',
                'name',
                'short_name',
                'cover_image',
                'spu'
            ])
            ->byCategory($lv3_id_arr)
            ->language($this->lang_id)
            ->enabled(true)
            ->onSale(true)
            ->onShelves(true)
            ->select()
            ->toArray();
        $product_groups = [];
        foreach ($products as $product) {
            $product_groups[$product['category_id']][] = $product;
        }
        foreach ($categorys as $key => $category) {
            if ($category['level'] < 3) continue;
            $categorys[$key]['products'] = $product_groups[$category['id']] ?? [];
        }

        $tree = array_to_tree($categorys, $pid);
        View::assign('categorys', $tree);

        return View::fetch('classify');
    }

    /**
     * 产品搜索
     */
    public function search()
    {
        $param = request()->param([
            'keywords',
            'page/d' => 1,
            'size/d' => 10
        ]);
        $keywords = !empty($param['keywords']) ? trim($param['keywords']) : '';

        // 关键词搜索
        $products = ProductModel::field([
                'id',
                'name',
                'short_name',
                'cover_image',
                'spu'
            ])
            ->where(fn ($query) => $query->withSearch(['keywords'], ['keywords' => $keywords]))
            ->language($this->lang_id)
            ->enabled(true)
            ->onSale(true)
            ->onShelves(true)
            ->order(['sort' => 'asc', 'id' => 'desc'])
            ->paginate([
                'list_rows' => $param['size'],
                'page'      => $param['page'],
                'query'     => request()->param()
            ])
            ->each(function ($item) use($keywords) {
                $replace            = fn($txt) => '<strong class="redpoint">' . $txt . '</strong>';
                $item['spu']        = highlight_keywords($item['spu'], $keywords, $replace);
                $item['name']       = highlight_keywords($item['name'], $keywords, $replace);
                $item['short_name'] = highlight_keywords($item['short_name'], $keywords, $replace);
                return $item;
            });
        View::assign('products', $products);
        View::assign('page', $products->render());

        return View::fetch('search');
    }

    /**
     * 产品详情页
     */
    public function detail()
    {
        $param = request()->param(['id']);

        // 获取产品信息
        $product = ProductModel::withoutField([
                'language_id',
                'status',
                'created_at',
                'updated_at',
                'deleted_at'
            ])
            ->bypk($param['id'])
            ->find();
        View::assign('product', $product);

        $product_categorys      = [];
        $product_params         = [];
        $product_skus           = [];
        $product_sku_attrs      = [];
        $product_purchase_links = [];
        $product_related        = [];
        if (!empty($product)) {
            // 获取产品分类信息
            $product_categorys = ProductCategoryModel::field(['id', 'pid', 'name'])
                ->bypk($product['category_id'])
                ->union(function($query) use($product) {
                    $query->name('product_category')
                        ->field(['id', 'pid', 'name'])
                        ->where('id', 'IN', function($sub_query) use($product) {
                            $sub_query->name('product_category')
                                ->where('id', '=', $product['category_id'])
                                ->field('path');
                        });
                })
                ->order(['id' => 'asc'])
                ->select()
                ->toArray();

            // 获取产品参数信息
            $product_params = ProductParamsModel::field(['id', 'name', 'value'])
                ->byProductId($product['id'])
                ->order(['id' => 'asc'])
                ->select()
                ->toArray();

            // 获取产品sku信息
            $skus = ProductSkuModel::withoutField(['created_at', 'updated_at'])
                ->byProductId($product['id'])
                ->order(['sort' => 'asc', 'id' => 'asc'])
                ->select();
            if (!empty($skus)) {
                $product_skus = $skus->toArray();

                // 获取产品sku属性信息
                $sku_attrs = ProductSkuAttrModel::bySkuId(array_unique(Arr::pluck($skus, 'id')))->select()->toArray();
                if (!empty($sku_attrs)) {
                    // 获取属性名称
                    $attrs = ProductAttrModel::bypks(array_unique(Arr::pluck($sku_attrs, 'attr_id')))->column(['attr_name'], 'id');
                    foreach ($sku_attrs as $v) {
                        if (empty($v['attr_value'])) continue;

                        $v['attr_name'] = $attrs[$v['attr_id']]?? '';
                        // 按属性分组
                        $product_sku_attrs[$v['attr_id']]['attr_id']       = $v['attr_id'];
                        $product_sku_attrs[$v['attr_id']]['attr_name']     = $v['attr_name'];
                        $product_sku_attrs[$v['attr_id']]['attr_values'][] = [
                            'sku_id'     => $v['sku_id'],
                            'attr_value' => $v['attr_value'],
                        ];
                    }
                    $product_sku_attrs = array_values($product_sku_attrs);
                }
            }

            // 获取产品购买链接信息
            $product_purchase_links = ProductPurchaseLinkModel::with(['platform'])
                ->field(['platform_id', 'link'])
                ->byProductId($product['id'])
                ->order(['sort' => 'asc', 'id' => 'desc'])
                ->select()
                ->hidden(['platform'])
                ->bindAttr('platform', ['platform_name' => 'platform', 'platform_sort' => 'sort'])
                ->toArray();
            // 根据购买链接平台排序
            $sort_by_arr = array_column($product_purchase_links, 'platform_sort');
            array_multisort($sort_by_arr, SORT_ASC, $product_purchase_links);

            // 获取相关产品信息
            $related = ProductRelatedModel::with(['product' => function($query) {
                    $query->field(['id', 'name', 'spu', 'cover_image']);
                }])
                ->byProductId($product['id'])
                ->order(['sort' => 'asc', 'id' => 'desc'])
                ->select();
            if (!$related->isEmpty()) {
                $product_related = Arr::pluck($related, 'product');
            }
        }
        View::assign('product_categorys', $product_categorys);            // 产品分类
        View::assign('product_params', $product_params);                  // 产品参数
        View::assign('product_skus', $product_skus);                      // 产品sku
        View::assign('product_sku_attrs', $product_sku_attrs);            // 产品sku属性
        View::assign('product_purchase_links', $product_purchase_links);  // 产品购买链接
        View::assign('product_related', $product_related);                // 相关产品

        // 获取询盘可选国家
        $config = $this->basic_config['optional_country_for_product_inquiry'];
        View::assign('country_list', explode(',', preg_replace('/\r?\n/', ',', $config['value']?? '')));

        return View::fetch('detail');
    }

    /**
     * 产品询盘
     */
    public function inquiry()
    {
        $post = request()->post([
            'first_name',
            'last_name',
            'email',
            'phone',
            'country_name',
            'corp_name',
            'industry',
            'message'
        ]);

        // 输出校验
        $validate = new ProductInquiryValidate;
        if (!$validate->check($post)) {
            return error($validate->getError());
        }

        // 保存询盘信息
        $ret = ProductInquiryModel::create([
            'language_id'  => $this->lang_id,
            'first_name'   => $post['first_name'],
            'last_name'    => $post['last_name'],
            'email'        => $post['email'],
            'phone'        => $post['phone'],
            'country_name' => $post['country_name'],
            'corp_name'    => $post['corp_name'],
            'industry'     => $post['industry'],
            'referer_url'  => request()->header('referer'),
            'message'      => $post['message'],
        ]);
        if ($ret->isEmpty()) {
            return error(lang('提交失败'));
        }
        return success(lang('提交成功'));
    }

    /**
     * 新品上市
     */
    public function newpro()
    {
        $focus_image = [];
        // 获取焦点图
        $banner = SysBannerModel::with(['items' => function($query) {
                $query->withoutField([
                        'status',
                        'created_at',
                        'updated_at',
                        'deleted_at'
                    ])
                    ->where('status', '=', 1)
                    ->order(['sort' => 'asc', 'id' => 'desc']);
            }])
            ->atPlatform(request()->from)
            ->uniqueLabel(['BANNER_680dd7ceaa529'])
            ->language($this->lang_id)
            ->enabled(true)
            ->select();
        if (!$banner->isEmpty()) {
            $focus_image = $banner->first()?->items ?? [];
        }
        View::assign('focus_image', $focus_image);

        $newpros = [];
        // 获取新品上市产品
        $products = ProductModel::field(['id', 'category_id', 'name', 'spu', 'cover_image', 'is_new'])
            ->language($this->lang_id)
            ->enabled(true)
            ->onSale(true)
            ->onShelves(true)
            ->isNew(true)
            ->order(['sort' => 'asc', 'id' => 'desc'])
            ->select();
        if (!$products->isEmpty()) {
            // 获取产品分类信息
            $categorys = ProductCategoryModel::field(['id', 'name', 'path', 'level'])
                ->where(function($query) use($products) {
                    $query->where('id', 'IN', Arr::pluck($products, 'category_id'))->whereOr('level', '=', 2);
                })
                ->language($this->lang_id)
                ->displayed(true)
                ->order(['sort' => 'asc', 'id' => 'asc'])
                ->select();
            if (!$categorys->isEmpty()) {
                // 根据产品分类path信息分组
                $map = [];
                foreach ($categorys as $category) {
                    $map[$category['id']] = $category;
                }
                $pro_map = [];
                foreach ($products as $pro) {
                    if (!isset($map[$pro['category_id']])) {
                        continue;
                    }
                    $m = $map[$pro['category_id']];
                    $pro_map[$m['path']][] = $pro;
                }

                // 获取二级分类下的产品信息
                foreach ($categorys as $val) {
                    if ($val['level'] != 2) {
                        continue;
                    }

                    foreach ($pro_map as $k => $pro) {
                        if (in_array($val['id'], explode(',', strval($k)))) {
                            $newpros[] = [
                                'category' => $val,
                                'products' => $pro,
                            ];
                            break;
                        }
                    }
                }
            }
        }
        View::assign('newpros', $newpros);

        return View::fetch('newpro');
    }
}
