package com.czg.controller.admin;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.entity.ShopInfo;
import com.czg.account.service.ShopInfoService;
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 jakarta.servlet.http.HttpServletResponse;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;


/**
 * 管理端/商品管理 - 商品列表
 *
 * @author Tankaikai tankaikai@aliyun.com
 * @since 1.0 2025-02-16
 */
@RestController
@RequestMapping("/admin/product")
public class ProductController {

    @Resource
    private ProductService productService;

    @Resource
    private ProdConsRelationService prodConsRelationService;

    @Resource
    private RabbitPublisher rabbitPublisher;

    @Resource
    private ShopSyncService shopSyncService;

    @Resource
    private ShopInfoService shopInfoService;

    /**
     * 商品-分页
     */
    @GetMapping("page")
    //@SaAdminCheckPermission("product:page")
    public CzgResult<Map<String, Object>> getProductPage(ProductDTO param) {
        Page<ProductDTO> data = productService.getProductPage(param);
        Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(data), Map.class);
        return CzgResult.success(map);
    }

    /**
     * 导出商品
     */
    @GetMapping("export")
    public void exportProduct(ProductDTO param, HttpServletResponse response) {
        productService.exportProductList(param, response);
    }

    /**
     * 商品-列表
     */
    @GetMapping("list")
    public CzgResult<List<ProductDTO>> getProductList(@RequestParam(required = false) Long categoryId) {
        return CzgResult.success(productService.getProductCacheList(StpKit.USER.getShopId(), categoryId));
    }

    /**
     * 商品-详情
     */
    @GetMapping("{id}")
    //@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();
        dto.setShopId(shopId);
        productService.addProduct(dto);
        asyncProductToShop(dto.getId());
        ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)));
        return CzgResult.success();
    }

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

    /**
     * 商品-修改
     */
    @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");
        }
        Long shopId = StpKit.USER.getShopId();
        dto.setShopId(shopId);
        productService.updateProduct(dto);
        asyncProductToShop(dto.getId());
        ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)));
        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();
        productService.deleteProduct(shopId, id);
        asyncProductToShop(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();
        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();
        param.setShopId(shopId);
        productService.markProductIsSoldOut(param);
        ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)));
        return CzgResult.success();
    }

    /**
     * 商品-标记自动售罄
     */
    @PostMapping("markIsAutoSoldOut")
    public CzgResult<Void> markIsAutoSoldOut(@RequestBody @Validated({DefaultGroup.class}) ProductIsAutoSaleParam param) {
        productService.markProductIsAutoSoldOut(StpKit.USER.getShopId(), param);
        ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(StpKit.USER.getShopId())));
        return CzgResult.success();
    }

    /**
     * 商品-绑定耗材
     */
    @PostMapping("bind")
    @OperationLog("商品-绑定耗材")
    //@SaAdminCheckPermission("product:bind")
    public CzgResult<Void> bindCons(@RequestBody @Validated({DefaultGroup.class}) ProdConsBindDTO param) {
        AssertUtil.isNull(param.getId(), "商品Id不能为空");
        prodConsRelationService.saveProdConsRelation(param);
        ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(StpKit.USER.getShopId())));
        asyncConsProToShop(param.getId());
        return CzgResult.success();
    }


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

    /**
     * 商品-统计
     */
    @GetMapping("statistics")
    //@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("batchOperate")
    public CzgResult<Void> batchOperate(ProductBatchParam param) {
        Long shopId = StpKit.USER.getShopId();
        param.setShopId(shopId);
        productService.batchOperate(param);
        return CzgResult.success();
    }

    /**
     * 商品-报损
     */
    @PostMapping("sync")
    @OperationLog("商品-同步主店商品信息")
    //@SaAdminCheckPermission("product:sync")
    public CzgResult<Void> sync() {
        long shopId = StpKit.USER.getShopId(0L);
        ShopInfo shopInfo = shopInfoService.getById(shopId);
        if (shopInfo == null) {
            throw new CzgException("店铺不存在");
        }
        AssertUtil.isNotEqual(shopInfo.getIsEnableProdSync(), 1, "主店未开启商品资料同步功能");

        if (shopInfo.getMainId() == null || shopId == shopInfo.getMainId()) {
            throw new CzgException("不存在主子店铺关系，无需同步商品信息");
        }
        ThreadUtil.execAsync(() -> shopSyncService.sync(shopInfo.getMainId(), shopId, shopId));
        CzgResult<Void> ret = CzgResult.success();
        ret.setMsg("操作成功，数据正在后台同步中...");
        return ret;
    }

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

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