package com.czg.controller.admin;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.annotation.SaStaffCheckPermission;
import com.czg.config.RabbitPublisher;
import com.czg.exception.CzgException;
import com.czg.log.annotation.OperationLog;
import com.czg.product.dto.ProdConsBindDTO;
import com.czg.product.dto.ProdSkuDTO;
import com.czg.product.dto.ProductDTO;
import com.czg.product.entity.ProductStockFlow;
import com.czg.product.param.*;
import com.czg.product.service.ProdConsRelationService;
import com.czg.product.service.ProductService;
import com.czg.product.service.ShopSyncService;
import com.czg.product.vo.ProductStatisticsVo;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import com.czg.utils.AssertUtil;
import com.czg.validator.ValidatorUtil;
import com.czg.validator.group.DefaultGroup;
import com.czg.validator.group.InsertGroup;
import com.czg.validator.group.UpdateGroup;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * 商品管理 - 商品列表
 *
 * @author Tankaikai tankaikai@aliyun.com
 * @since 1.0 2025-02-16
 */
@AllArgsConstructor
@RestController
@RequestMapping("/admin/product")
public class ProductController {
    private final ProductService productService;
    private final ProdConsRelationService prodConsRelationService;
    private final RabbitPublisher rabbitPublisher;
    @Resource
    private ShopSyncService shopSyncService;

    /**
     * 商品-分页
     */
    @GetMapping("page")
    @OperationLog("商品-分页")
    //@SaAdminCheckPermission("product:page")
    public CzgResult<Page<ProductDTO>> getProductPage(ProductDTO param) {
        Page<ProductDTO> data = productService.getProductPage(param);
        return CzgResult.success(data);
    }

    /**
     * 商品-列表
     */
    @GetMapping("list")
    @OperationLog("商品-列表")
    //@SaAdminCheckPermission("product:list")
    public CzgResult<List<ProductDTO>> getProductList(ProductDTO param) {
        Long shopId = StpKit.USER.getShopId(0L);
        param.setShopId(shopId);
        ProductDTO cacheParam = new ProductDTO();
        cacheParam.setShopId(shopId);
        List<ProductDTO> data = getProductCacheList(cacheParam, param);
        productService.refreshProductStock(param, data);
        return CzgResult.success(data);
    }

    private List<ProductDTO> getProductCacheList(ProductDTO cacheParam, ProductDTO param) {
        List<ProductDTO> productList = productService.getProductList(cacheParam);
        if (StrUtil.isNotEmpty(param.getName())) {
            productList = productList.stream().filter(obj -> StrUtil.contains(obj.getName(), param.getName())).toList();
        }
        if (ObjUtil.isNotNull(param.getCategoryId())) {
            productList = productList.stream().filter(obj -> param.getCategoryId().equals(obj.getCategoryId())).toList();
        }
        return productList;
    }

    /**
     * 商品-详情
     */
    @GetMapping("{id}")
    @OperationLog("商品-详情")
    //@SaAdminCheckPermission("product:info")
    public CzgResult<ProductDTO> getProductById(@PathVariable("id") Long id) {
        AssertUtil.isNull(id, "{}不能为空", "id");
        ProductDTO data = productService.getProductById(id);
        return CzgResult.success(data);
    }

    /**
     * 商品-新增
     */
    @PostMapping
    @OperationLog("商品-新增")
    //@SaAdminCheckPermission("product:add")
    public CzgResult<Void> addProduct(@RequestBody @Validated({InsertGroup.class, DefaultGroup.class}) ProductDTO dto) {
        AssertUtil.isListEmpty(dto.getSkuList(), "商品SKU不能为空");
        for (ProdSkuDTO prodSkuDTO : dto.getSkuList()) {
            ValidatorUtil.validateEntity(prodSkuDTO, DefaultGroup.class);
        }
        Long shopId = StpKit.USER.getShopId(0L);
        dto.setShopId(shopId);
        productService.addProduct(dto);
        asyncToBranchShop(dto.getId());
        ThreadUtil.execAsync(() -> {
            rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId));
        });
        return CzgResult.success();
    }

    /**
     * 商品-修改
     */
    @PutMapping
    @OperationLog("商品-修改")
    @SaStaffCheckPermission("yun_xu_xiu_gai_shang_pin")
    //@SaAdminCheckPermission("product:update")
    public CzgResult<Void> updateProduct(@RequestBody @Validated({UpdateGroup.class, DefaultGroup.class}) ProductDTO dto) {
        if (dto.getCategoryId() != null) {
            StpKit.USER.checkStaffPermission("yun_xu_xiu_gai_fen_lei");
        }

        if (dto.getGroupCategoryId() != null) {
            StpKit.USER.checkStaffPermission("yun_xu_xiu_gai_fen_zu");
        }

        if (dto.getStockNumber() != null) {
            StpKit.USER.checkStaffPermission("yun_xu_xiu_gai_shang_pin_ku_cun");
        }
        Long shopId = StpKit.USER.getShopId(0L);
        dto.setShopId(shopId);
        productService.updateProduct(dto);
        asyncToBranchShop(dto.getId());
        ThreadUtil.execAsync(() -> {
            rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId));
        });
        return CzgResult.success();
    }

    @PostMapping("modifyStock")
    @OperationLog("商品-修改库存")
    @SaStaffCheckPermission("yun_xu_xiu_gai_shang_pin")
    public CzgResult<Void> updateProductStock(@RequestBody ProductModifyStockParam param) {
        ValidatorUtil.validateEntity(param, DefaultGroup.class);
        Long shopId = StpKit.USER.getShopId(0L);
        param.setShopId(shopId);
        productService.updateProductStock(param);
        return CzgResult.success();
    }

    /**
     * 商品-删除
     *
     * @param id 商品ID
     */
    @DeleteMapping("{id}")
    @OperationLog("商品-删除")
    @SaStaffCheckPermission("yun_xu_xiu_gai_shang_pin")
    //@SaAdminCheckPermission("product:delete")
    public CzgResult<Void> deleteProduct(@PathVariable("id") Long id) {
        //效验数据
        AssertUtil.isNull(id, "{}不能为空", "id");
        Long shopId = StpKit.USER.getShopId(0L);
        productService.deleteProduct(shopId, id);
        asyncToBranchShop(id);
        ThreadUtil.execAsync(() -> {
            rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId));
        });
        return CzgResult.success();
    }

    /**
     * 商品-上下架
     */
    @PostMapping("onOff")
    @OperationLog("商品-上下架")
    @SaStaffCheckPermission("yun_xu_shang_xia_jia_shang_pin")
    //@SaAdminCheckPermission("product:on-off")
    public CzgResult<Void> onOffProduct(@RequestBody @Validated({DefaultGroup.class}) ProductIsSaleParam param) {
        Long shopId = StpKit.USER.getShopId(0L);
        param.setShopId(shopId);
        productService.onOffProduct(param);
        ThreadUtil.execAsync(() -> {
            rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId));
        });
        return CzgResult.success();
    }

    /**
     * 商品-标记售罄
     */
    @PostMapping("markIsSoldOut")
    @OperationLog("商品-标记售罄")
    @SaStaffCheckPermission("yun_xu_shou_qing_shang_pin")
    //@SaAdminCheckPermission("product:markIsSoldOut")
    public CzgResult<Void> markIsSoldOutProduct(@RequestBody @Validated({DefaultGroup.class}) ProductIsSoldOutParam param) {
        Long shopId = StpKit.USER.getShopId(0L);
        param.setShopId(shopId);
        productService.markProductIsSoldOut(param);
        ThreadUtil.execAsync(() -> {
            rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId));
        });
        return CzgResult.success();
    }

    /**
     * 商品-绑定耗材
     */
    @PostMapping("bind")
    @OperationLog("商品-绑定耗材")
    //@SaAdminCheckPermission("product:bind")
    public CzgResult<Void> bindCons(@RequestBody @Validated({DefaultGroup.class}) ProdConsBindDTO param) {
        prodConsRelationService.saveProdConsRelation(param);
        asyncToBranchShop2(param.getId());
        return CzgResult.success();
    }

    /**
     * 商品-退款退至库存
     */
    @PostMapping("refundToStock")
    @OperationLog("商品-退款退至库存")
    //@SaAdminCheckPermission("product:update")
    public CzgResult<Void> refundToStock(@RequestBody @Validated({DefaultGroup.class}) ProdRefundToStockParam param) {
        productService.refundToStock(param);
        asyncToBranchShop(param.getId());
        return CzgResult.success();
    }

    /**
     * 商品-库存预警设置
     */
    @PostMapping("stockWarning")
    @OperationLog("商品-库存预警设置")
    //@SaAdminCheckPermission("product:stockWarning")
    public CzgResult<Void> stockWarning(@RequestParam Integer warnLine) {
        AssertUtil.isNull(warnLine, "{}不能为空", "warnLine");
        if (warnLine < 0) {
            throw new CzgException("预警值不能小于0");
        }
        productService.stockWarning(warnLine);
        return CzgResult.success();
    }

    /**
     * 商品-报损
     */
    @PostMapping("reportDamage")
    @OperationLog("商品-报损")
    @SaStaffCheckPermission("yun_xu_ti_jiao_bao_sun")
    //@SaAdminCheckPermission("product:reportDamage")
    public CzgResult<Void> reportDamage(@RequestBody ProductReportDamageParam param) {
        ValidatorUtil.validateEntity(param, DefaultGroup.class);
        productService.reportDamage(param);
        return CzgResult.success();
    }

    /**
     * 商品-统计
     */
    @GetMapping("statistics")
    @OperationLog("商品-统计")
    //@SaAdminCheckPermission("product:statistics")
    public CzgResult<ProductStatisticsVo> statistics(ProductInfoParam param) {
        Long shopId = StpKit.USER.getShopId(0L);
        param.setShopId(shopId);
        ProductStatisticsVo data = productService.getProductStatistics(param);
        return CzgResult.success(data);
    }

    /**
     * 商品-库存变动记录
     */
    @GetMapping("stockFlow")
    @OperationLog("商品-库存变动记录")
    //@SaAdminCheckPermission("consStockFlow:flow")
    public CzgResult<Page<ProductStockFlow>> stockFlow(ProductStockFlowParam param) {
        Page<ProductStockFlow> data = productService.findProductStockFlowPage(param);
        return CzgResult.success(data);
    }

    private void asyncToBranchShop(Long id) {
        long shopId = StpKit.USER.getShopId(0L);
        long sysUserId = StpKit.USER.getLoginIdAsLong();
        ThreadUtil.execAsync(() -> {
            shopSyncService.syncProductBySourceShop(shopId, id, sysUserId);
        });
    }

    private void asyncToBranchShop2(Long id) {
        long shopId = StpKit.USER.getShopId(0L);
        long sysUserId = StpKit.USER.getLoginIdAsLong();
        ThreadUtil.execAsync(() -> {
            shopSyncService.syncConsProBySourceShop(shopId, id, sysUserId);
        });
    }

}
