package cn.newfeifan.mall.sale.service.merchant;

import cn.newfeifan.mall.framework.common.exception.ErrorCode;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
import cn.newfeifan.mall.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO;
import cn.newfeifan.mall.module.product.dal.dataobject.spuapply.SpuApplyDO;
import cn.newfeifan.mall.module.product.enums.spu.ProductSpuStatusEnum;
import cn.newfeifan.mall.module.product.service.sku.ProductSkuService;
import cn.newfeifan.mall.module.product.service.spuapply.SpuApplyService;
import cn.newfeifan.mall.module.promotion.controller.admin.diy.vo.template.DiyTemplateCreateReqVO;
import cn.newfeifan.mall.module.promotion.controller.admin.diy.vo.template.DiyTemplateUpdateReqVO;
import cn.newfeifan.mall.module.promotion.dal.dataobject.diy.DiyTemplateDO;
import cn.newfeifan.mall.module.promotion.service.diy.DiyTemplateService;
import cn.newfeifan.mall.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.newfeifan.mall.module.system.dal.dataobject.user.AdminUserDO;
import cn.newfeifan.mall.module.system.dal.mysql.user.AdminUserMapper;
import cn.newfeifan.mall.module.system.mq.message.login.LoginSendMessage;
import cn.newfeifan.mall.module.system.service.user.AdminUserService;
import cn.newfeifan.mall.module.trade.service.order.TradeOrderQueryService;
import cn.newfeifan.mall.sale.controller.admin.merchant.vo.MerchantPageReqVO;
import cn.newfeifan.mall.sale.controller.admin.merchant.vo.MerchantRespVO;
import cn.newfeifan.mall.sale.controller.admin.merchant.vo.MerchantSaveReqVO;
import cn.newfeifan.mall.sale.controller.admin.shop.vo.ShopRespVO;
import cn.newfeifan.mall.sale.dal.dataobject.merchant.MerchantDO;
import cn.newfeifan.mall.sale.dal.dataobject.merchantapply.MerchantApplyDO;
import cn.newfeifan.mall.sale.dal.mysql.merchant.MerchantMapper;
import cn.newfeifan.mall.sale.dal.mysql.merchantapply.MerchantApplyMapper;
import cn.newfeifan.mall.sale.dal.redis.ShopMessage;
import cn.newfeifan.mall.sale.service.shop.ShopService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import cn.newfeifan.mall.framework.common.util.object.BeanUtils;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.module.enums.ErrorCodeConstants.MERCHANT_NOT_EXISTS;

/**
 * 商户 Service 实现类
 *
 * @author 非繁人
 */
@Service
@Validated
public class MerchantServiceImpl implements MerchantService {

    @Resource
    private MerchantMapper merchantMapper;

    @Resource
    private AdminUserMapper userMapper;
    @Resource
    private AdminUserService adminUserService;

    @Resource
    private ShopService shopService;
    @Resource
    private SpuApplyService spuApplyService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private MerchantApplyMapper merchantApplyMapper;
    @Resource
    private DiyTemplateService diyTemplateService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HashMap<String, Long> createMerchant(MerchantSaveReqVO createReqVO, String mobile) {
        // 插入
        MerchantDO merchant = BeanUtils.toBean(createReqVO, MerchantDO.class);
        merchantMapper.insert(merchant);

        // 创建一个店铺
        Long shopId = shopService.createShop(merchant, createReqVO);
        // 创建商户的时候, 根据手机号, 创建一个新的账号
        // 如果这个手机号已经存在, 则提示该手机号已经存在
        AdminUserDO adminUserDO = userMapper.selectByMobile(merchant.getContactNumber());
        if (adminUserDO != null) {
            ErrorCode ERROR = new ErrorCode(1_002_003_001, "用户手机号已经存在商户账号");
            throw exception(ERROR);
        }
        adminUserService.createUserByMobile(merchant.getId(), shopId, merchant.getContactNumber(), merchant.getContact(), true);

        // 不同的手机号, 创建不同的账号
        if (mobile != null) {
            AdminUserDO userDO = userMapper.selectByMobile(mobile);
            if (userDO != null) {
                ErrorCode ERROR = new ErrorCode(1_002_003_001, "联络人手机号已经存在商户账号");
                throw exception(ERROR);
            }
            adminUserService.createUserByMobile(merchant.getId(), shopId, mobile, merchant.getContact(),false);
        }
        // todo 设置直推人关联关系
        HashMap<String, Long> stringLongHashMap = new HashMap<>();
        stringLongHashMap.put("shopId", shopId);
        stringLongHashMap.put("merId", merchant.getId());

        // 创建店铺模板
        DiyTemplateCreateReqVO build = DiyTemplateCreateReqVO.builder().merchantId(merchant.getId()).shopId(shopId).build();
        build.setName(merchant.getName());
        diyTemplateService.createDiyTemplate(build);
        return stringLongHashMap;
    }

    @Override
    public void updateMerchant(MerchantSaveReqVO updateReqVO) {
        // 校验存在
        validateMerchantExists(updateReqVO.getId());
        // 更新
        MerchantDO updateObj = BeanUtils.toBean(updateReqVO, MerchantDO.class);
        merchantMapper.updateById(updateObj);

        MerchantApplyDO bean = BeanUtils.toBean(updateReqVO, MerchantApplyDO.class);
        bean.setId(updateObj.getMerchantApplyId());
        merchantApplyMapper.updateById(bean);

        DiyTemplateDO usedDiyTemplate = diyTemplateService.getUsedDiyTemplate(updateObj.getId());
        usedDiyTemplate.setName(updateObj.getName());
        diyTemplateService.updateDiyTemplate(BeanUtils.toBean(usedDiyTemplate, DiyTemplateUpdateReqVO.class));
    }

    @Override
    public void deleteMerchant(Long id) {
        // 校验存在
//        validateMerchantExists(id);
        List<SpuApplyDO> spuApplyDOS = spuApplyService.selectListByMerId(id);
        spuApplyDOS.forEach(spuApplyDO -> {
        ProductSpuUpdateStatusReqVO build = new ProductSpuUpdateStatusReqVO().setId(spuApplyDO.getId()).setStatus(ProductSpuStatusEnum.DISABLE.getStatus());
            spuApplyService.updateSpuStatus(build);
        });


//        spuApplyDOS.forEach(spuApplyDO -> {
//                    spuApplyService.deleteSpuApply(spuApplyDO.getId());
//        });

        // 删除
        merchantMapper.deleteById(id);
    }

    private void validateMerchantExists(Long id) {
        if (merchantMapper.selectById(id) == null) {
            throw exception(MERCHANT_NOT_EXISTS);
        }
    }

    @Override
    public MerchantDO getMerchant(Long id) {
        return merchantMapper.selectById(id);
    }

    @Override
    public PageResult<MerchantDO> getMerchantPage(MerchantPageReqVO pageReqVO) {
        return merchantMapper.selectPage(pageReqVO);
    }

    @Resource
    private TradeOrderQueryService tradeOrderQueryService;

    @Resource
    private ProductSkuService productSkuService;

    @Override
    public List<MerchantRespVO> salesVolume(Map<Long, MerchantRespVO> map) {

        for (Long key : map.keySet()) {
            System.out.println("Key = " + key);
            MerchantRespVO value = map.get(key);
            Integer saleVolume = tradeOrderQueryService.getShopSalesVolume(key);
            Integer skuCount = productSkuService.getSkuCount(key);
            value.setSalesVolume(saleVolume);
            value.setSkuCount(skuCount);
            map.put(key, value);
        }
        return new ArrayList<>(map.values());
    }

    @Override
    public void doSendMail(LoginSendMessage message) {

        // 查询用户的商户信息,并且缓存到redis中
        OAuth2AccessTokenDO oAuth2AccessTokenDO = message.getOAuth2AccessTokenDO();
        ShopMessage shopMessage = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get("shop:" + message.getOAuth2AccessTokenDO().getUserId()), ShopMessage.class);
        if (shopMessage != null) {
            // 刷新时间
            stringRedisTemplate.opsForValue().set("shop:" + oAuth2AccessTokenDO.getUserId(), JsonUtils.toJsonString(shopMessage), 3600 * 24, TimeUnit.SECONDS);
        } else {
            // 查询数据库
            AdminUserDO adminUserDO = userMapper.selectById(message.getOAuth2AccessTokenDO().getUserId());
            if (adminUserDO.getShopId() != null) {
                ShopMessage addRedis = new ShopMessage().setShopId(adminUserDO.getShopId()).setMerId(adminUserDO.getMerchantId());
                stringRedisTemplate.opsForValue().set("shop:" + oAuth2AccessTokenDO.getUserId(), JsonUtils.toJsonString(addRedis), 3600 * 24, TimeUnit.SECONDS);
            } else {
                // 获取随机店铺
                List<ShopRespVO> merchantAllShop = shopService.getMerchantAllShop(adminUserDO.getMerchantId());
                oAuth2AccessTokenDO.setMerchantId(adminUserDO.getMerchantId());
                Long shopId = null;
                if (merchantAllShop.size() > 0) {
                    shopId = merchantAllShop.get(0).getId();
                    oAuth2AccessTokenDO.setShopId(shopId);
                }
                //存储redis
                ShopMessage addRedis = new ShopMessage().setShopId(shopId).setMerId(adminUserDO.getMerchantId());
                stringRedisTemplate.opsForValue().set("shop:" + oAuth2AccessTokenDO.getUserId(), JsonUtils.toJsonString(addRedis), 3600 * 24, TimeUnit.SECONDS);
            }
        }
    }

    @Override
    public MerchantDO selectByApplyId(Long id) {
        return merchantMapper.selectOne(MerchantDO::getMerchantApplyId, id);
    }

    @Override
    public void updateMerchant(MerchantDO merchantDO) {
        merchantMapper.updateById(merchantDO);
    }
}