/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.mall.controller;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.common.enums.StatusEnum;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.node.TreeNode;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.mall.entity.CategoryInfo;
import org.springblade.modules.mall.entity.GoodsInfo;
import org.springblade.modules.mall.service.ICategoryInfoService;
import org.springblade.modules.mall.service.impl.GoodsInfoServiceImpl;
import org.springblade.modules.mall.vo.CategoryInfoVO;
import org.springblade.modules.mall.wrapper.CategoryInfoWrapper;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 类别表 控制器
 *
 * @author BladeX
 * @since 2022-05-07
 */
@RestController
@AllArgsConstructor
@RequestMapping("mall/categoryinfo")
@Api(value = "类别表", tags = "类别表接口")
public class CategoryInfoController extends BladeController {

	private final ICategoryInfoService categoryInfoService;

	@Resource
	private GoodsInfoServiceImpl goodsInfoService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入categoryInfo")
	public R<CategoryInfoVO> detail(CategoryInfo categoryInfo) {
		CategoryInfo detail = categoryInfoService.getOne(Condition.getQueryWrapper(categoryInfo));
		List<Long> parentId = this.findParentId(categoryInfo.getId(), new ArrayList<>());
		CategoryInfoVO categoryInfoVO = CategoryInfoWrapper.build().entityVO(detail);
		categoryInfoVO.setParentIdArr(parentId);
		return R.data(categoryInfoVO);
	}

	/**
	 * 分页 类别表
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入categoryInfo")
	public R<IPage<CategoryInfoVO>> list(CategoryInfo categoryInfo, Query query) {
		IPage<CategoryInfo> pages = categoryInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(categoryInfo));
		return R.data(CategoryInfoWrapper.build().pageVO(pages));
	}


	/**
	 * 自定义分页 类别表
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入categoryInfo")
	public R<IPage<CategoryInfoVO>> page(CategoryInfoVO categoryInfo, Query query) {
		IPage<CategoryInfoVO> pages = categoryInfoService.selectCategoryInfoPage(Condition.getPage(query), categoryInfo);
		return R.data(pages);
	}

	/**
	 * 新增 类别表
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入categoryInfo")
	public R save(@Valid @RequestBody CategoryInfo categoryInfo) {
		if (categoryInfo.getParentId() == null) {
			categoryInfo.setParentId(0L);
		}
		return R.status(categoryInfoService.save(categoryInfo));
	}

	/**
	 * 修改 类别表
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入categoryInfo")
	public R update(@Valid @RequestBody CategoryInfo categoryInfo) {
		return R.status(categoryInfoService.updateById(categoryInfo));
	}

	/**
	 * 新增或修改 类别表
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入categoryInfo")
	public R submit(@Valid @RequestBody CategoryInfo categoryInfo) {
		if (categoryInfo.getParentId() == null || categoryInfo.getParentId() == 0L ) {
			categoryInfo.setParentId(0L);
			categoryInfo.setLevel(0);
		} else {
			CategoryInfo parent = categoryInfoService.getById(categoryInfo.getParentId());
			categoryInfo.setLevel(parent.getLevel() + 1);
		}
		if (categoryInfo.getId() == null) {
			CategoryInfo category = categoryInfoService.getOne(Wrappers.lambdaQuery(CategoryInfo.class)
				.eq(CategoryInfo::getTitle, categoryInfo.getTitle()).eq(CategoryInfo::getParentId, categoryInfo.getParentId()));
			if (category != null) {
				return R.fail("分类已存在");
			}
		}
		return R.status(categoryInfoService.saveOrUpdate(categoryInfo));
	}


	/**
	 * 删除 类别表
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(categoryInfoService.removeByIds(Func.toLongList(ids)));
	}

	/**
	 * 懒加载列表
	 */
	@GetMapping("/lazy-list")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "懒加载列表", notes = "传入Category")
	public R<List<CategoryInfoVO>> lazyList(Long parentId, @ApiIgnore @RequestParam Map<String, Object> menu) {
		List<CategoryInfoVO> list = categoryInfoService.lazyList(parentId, menu);
		return R.data(CategoryInfoWrapper.build().listNodeLazyVO(list));
	}

	/**
	 * 懒加载列表
	 */
	@GetMapping("/getByParentId/{parentId}")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "根据父id查询")
	public R<List<CategoryInfoVO>> getByParentId(@PathVariable("parentId") Long parentId) {
		List<CategoryInfo> categoryInfos = categoryInfoService.lambdaQuery().eq(CategoryInfo::getState, StatusEnum.ENABLE.getValue()).eq(CategoryInfo::getParentId, parentId).orderByAsc(CategoryInfo::getSort).list();
		List<CategoryInfoVO> treeNodes = new ArrayList<>();
		for (CategoryInfo categoryInfo : categoryInfos) {
			CategoryInfoVO treeNode = new CategoryInfoVO();
			treeNode.setTitle(categoryInfo.getTitle());
			treeNode.setLevel(categoryInfo.getLevel());
			treeNode.setState(categoryInfo.getState());
			treeNode.setSort(categoryInfo.getSort());
			treeNode.setLogo(categoryInfo.getLogo());
			treeNode.setParentId(categoryInfo.getParentId());
			treeNode.setKey(categoryInfo.getId());
			treeNode.setId(categoryInfo.getId());
			treeNode.setHasChildren(true);
			treeNodes.add(treeNode);
		}
		return R.data(treeNodes);
	}

	/**
	 * 获取树形结构
	 */
	@GetMapping("/tree")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "树形结构", notes = "树形结构")
	public R<List<TreeNode>> tree(@RequestParam(value = "flag", required = false) String flag) {
		List<TreeNode> treeNodes = categoryInfoService.tree();
		return R.data(treeNodes);
	}


	@PostMapping("/updateBatch")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "批量修改", notes = "传入ids")
	public R updateBatch(@RequestParam String ids, @RequestParam Long parentId) {
		List<Long> list = Func.toLongList(ids);
		// 查询当前id的所有父id
		List<Long> parentIds = this.findParentId(parentId, new ArrayList<>());
		List<CategoryInfo> categoryInfos = categoryInfoService.lambdaQuery().in(CategoryInfo::getId, list).list();
		Map<Long, CategoryInfo> categoryInfoMap = categoryInfos.stream().collect(Collectors.toMap(CategoryInfo::getId, Function.identity()));
		for (Long id : list) {
			List<Long> parentId1 = this.findParentId(id, new ArrayList<>());
			String queryCId = parentId1.size() == 1 ? CollUtil.join(parentId1, "-") + "-" : CollUtil.join(parentId1, "-");

			CategoryInfo categoryInfo = categoryInfoMap.get(id);
			List<Long> longs = parentId1.subList(categoryInfo.getLevel(), parentId1.size());
			List<Long> parentIdCopy = CollUtil.newArrayList(parentIds);
			parentIdCopy.addAll(longs);

			List<GoodsInfo> goodsInfos = goodsInfoService.lambdaQuery().likeRight(GoodsInfo::getGoodsCategoryId, queryCId).list();
			for (GoodsInfo goodsInfo : goodsInfos) {
				String newCategoryId = goodsInfo.getGoodsCategoryId().replace(CollUtil.join(parentId1, "-"), CollUtil.join(parentIdCopy, "-"));
				goodsInfo.setGoodsCategoryId(newCategoryId + "-");
			}
			goodsInfoService.updateBatchById(goodsInfos);
		}
		for (Long a : list) {
			if (!a.equals(parentId)) {
				categoryInfoService.lambdaUpdate().set(CategoryInfo::getParentId, parentId).eq(CategoryInfo::getId, a).update();
			}
		}
		return R.success("操作成功");
	}

	/**
	 * 查询当前id的所有父id
	 * @param parentId
	 * @param idStr
	 * @return
	 */
	private List<Long> findParentId(Long parentId, List<Long> idStr) {
		CategoryInfo categoryInfo = categoryInfoService.getById(parentId);
		if (categoryInfo.getParentId() == 0L) {
			idStr.add(0, categoryInfo.getId());
			return idStr;
		}
		idStr.add(0, categoryInfo.getId());
		return this.findParentId(categoryInfo.getParentId(), idStr);
	}
}
