package com.tzy.controller.group;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tzy.annotation.ApiLog;
import com.tzy.app.domain.AppBaseUser;
import com.tzy.app.domain.AppUserDetailInfo;
import com.tzy.app.domain.order.OrderListDTO;
import com.tzy.app.dto.mq.GoodsListDTO;
import com.tzy.app.service.AppUserDetailInfoService;
import com.tzy.app.service.IAppBaseUserService;
import com.tzy.common.constant.Constants;
import com.tzy.common.constant.MsgConstants;
import com.tzy.common.constant.NoticeMsgModel;
import com.tzy.common.core.domain.AjaxResult;
import com.tzy.common.dto.InDto;
import com.tzy.common.dto.OutDTO;
import com.tzy.common.dto.UserInfo;
import com.tzy.common.dto.order.OrderStatusDTO;
import com.tzy.common.enums.BusinessType;
import com.tzy.common.exception.AppAssert;
import com.tzy.common.exception.ServiceException;
import com.tzy.common.utils.DateUtils;
import com.tzy.common.utils.ServletUtils;
import com.tzy.common.utils.UserUtils;
import com.tzy.dto.AuctionJPushDTO;
import com.tzy.dto.local.*;
import com.tzy.framework.util.RedisUtils;
import com.tzy.member.benefits.dto.OrderSubmitDTO;
import com.tzy.pojo.card.CardGroupOrderInfo;
import com.tzy.pojo.item.Sku;
import com.tzy.service.SkuService;
import com.tzy.sportcard.api.bean.act.AppActPrize;
import com.tzy.sportcard.api.domain.AppUserInfoDto;
import com.tzy.sportcard.api.domain.GroupInfo;
import com.tzy.sportcard.api.domain.MerchantInfo;
import com.tzy.sportcard.api.dto.AuctionOrderDTO;
import com.tzy.sportcard.api.dto.LiveDTO;
import com.tzy.sportcard.api.dto.ResourceData;
import com.tzy.sportcard.api.dto.group.GroupStatusInfoDto;
import com.tzy.sportcard.api.dto.group.ProductPromGroupInfoDto;
import com.tzy.sportcard.api.dto.merchant.MerchantScoreDTO;
import com.tzy.sportcard.api.dto.prize.PublicCodeParam;
import com.tzy.sportcard.api.dto.prize.PublicCodeResultDTO;
import com.tzy.sportcard.api.service.*;
import com.tzy.sportcard.group.domain.CardGroupLivesConfig;
import com.tzy.sportcard.group.dto.MerchantAvatarsDTO;
import com.tzy.sportcard.group.dto.OrderCallBackDTO;
import com.tzy.sportcard.group.mapper.CardGroupLivesConfigMapper;
import com.tzy.sportcard.group.service.AppActService;
import com.tzy.sportcard.group.service.ICardGroupInfoService;
import com.tzy.sportcard.group.service.ICardGroupOrderInfoService;
import com.tzy.sportcard.group.service.ITzyMerchantInfoService;
import com.tzy.system.domain.TzyShippingAddress;
import com.tzy.system.domain.TzySysNoticeRecord;
import com.tzy.system.mapper.TzyShippingAddressMapper;
import com.tzy.system.service.ITzySysNoticeRecordService;
import com.tzy.util.NoticeType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.common.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.teasoft.bee.osql.SuidRich;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author by po'yi
 * @Classname GroupControllerNew
 * @Description
 * @Date 2022/11/24 13:24
 */
@Api(value = "内网访问组团新接口")
@RestController
@RequestMapping("/api/local")
@Slf4j
public class GroupLocalController {

    @Autowired
    private SuidRich suidRich;
    @Resource
    private IAllocateGoodsService allocateGoodsService;
    @Autowired
    private AppActService appActService;
    @Autowired
    private AsyncAppService asyncAppService;
    @Autowired
    private RedisUtils redisUtils;
    @Resource
    private MineApiService mineApiService;
    @Resource
    private AuctionOrderService auctionOrderService;
    @Resource
    private ITzySysNoticeRecordService noticeRecordService;
    @Resource
    private IAppBaseUserService appBaseUserService;
    @Resource
    private CardGroupLivesConfigMapper cardGroupLivesConfigMapper;
    @Autowired
    private GroupApiService groupApiService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private TzyShippingAddressMapper tzyShippingAddressMapper;
    @Resource
    private ICardGroupOrderInfoService cardGroupOrderInfoService;
    @Resource
    private ITzyMerchantInfoService tzyMerchantInfoService;
    @Autowired
    private MerchantApiService merchantApiService;
    @Resource
    private ICardGroupInfoService cardGroupInfoService;
    @Resource
    private AppUserDetailInfoService appUserDetailInfoService;

    @PostMapping("/free/mallOrder/{orderId}")
    public ResultDTO freeMallOrder(@PathVariable Long orderId) {
        com.tzy.sportcard.group.domain.CardGroupOrderInfo cardGroupOrderInfo = cardGroupOrderInfoService.selectCardGroupOrderInfoById(orderId);
        String orderNo = cardGroupOrderInfo.getOrderNo();
        log.info("商城免单：{}", orderNo);
        ResourceData resourceData = freePayBuild(orderNo, "商城免单");
        if(cardGroupOrderInfo.getActualPayment().compareTo(BigDecimal.ZERO) <= 0
                && cardGroupOrderInfo.getPoint() == 0
                && cardGroupOrderInfo.getGiveOrderId() == null
        ){
            return groupApiService.mallOrderCallBack(resourceData, cardGroupOrderInfo)
                    ? ResultDTO.buildEmptySuccess()
                    : ResultDTO.buildErrorResult();
        }
        return ResultDTO.buildErrorResult();

    }

    private ResourceData freePayBuild(String orderNo, String payType) {
        ResourceData resourceData = new ResourceData();
        ResourceData.PayAmount payAmount = new ResourceData.PayAmount();
        payAmount.setTotal(0);
        payAmount.setPayer_total(0);
        resourceData.setAmount(payAmount);
        resourceData.setTrade_type(payType);
        resourceData.setSubPaymentType(payType);
        resourceData.setBank_type(payType);
        resourceData.setOut_trade_no(orderNo);
        resourceData.setTransaction_id(String.valueOf(System.currentTimeMillis()));
        resourceData.setSuccess_time(DateUtils.dateTime(new Date()));
        resourceData.setTrade_state("TRADE_SUCCESS");
        resourceData.setTrade_state_desc("TRADE_SUCCESS");
        return resourceData;
    }

    @PostMapping("/get/address/{userId}")
    public ResultDTO address(@PathVariable Long userId) {
        List<TzyShippingAddress> list = tzyShippingAddressMapper.findFirstAddressByUserId(userId);
        return ResultDTO.buildSuccessResult(AddressDTO.builder().address(!CollectionUtils.isEmpty(list)).build());
    }

    @PostMapping("/get/explain/{liveId}")
    public ResultDTO getLivingExplain(@PathVariable Long liveId) {
        LivingExplainDTO livingExplainDTO =
                suidRich.selectOne(LivingExplainDTO.builder().liveId(liveId).status(1).build());
        return ResultDTO.buildSuccessResult(livingExplainDTO);
    }

    @PostMapping("/close/explain/{liveId}")
    public ResultDTO closeLivingExplain(@PathVariable Long liveId) {
        LivingExplainDTO livingExplainDTO =
                suidRich.selectOne(LivingExplainDTO.builder().liveId(liveId).status(1).build());
        if (Objects.nonNull(livingExplainDTO)) {
            suidRich.update(LivingExplainDTO.builder().id(livingExplainDTO.getId()).status(2).build());
        }
        return ResultDTO.buildEmptySuccess();
    }

    @PostMapping("/get/sku/{skuId}")
    public ResultDTO getSku(@PathVariable Integer skuId) {
        Sku sku = skuService.selectSkuByIdAndStatus(skuId, 101L);
        return ResultDTO.buildSuccessResult(sku);
    }

    @PostMapping("/get/live/{liveId}")
    public ResultDTO findLive(@PathVariable Long liveId) {
        CardGroupLivesConfig config = cardGroupLivesConfigMapper.selectCardGroupLivesConfigById(liveId);
        return ResultDTO.buildSuccessResult(config);
    }

    @PostMapping("/get/live/list")
    public ResultDTO findLive(@RequestBody LiveDTO liveDTO) {
        List<CardGroupLivesConfig> list = Lists.newArrayList();
        for (Long liveId : liveDTO.getIds()) {
            CardGroupLivesConfig config = cardGroupLivesConfigMapper.selectCardGroupLivesConfigById(liveId);
            if (Objects.nonNull(config)) {
                if (!Objects.equals(config.getStatus(), 0L) && !Objects.equals(config.getStatus(), 1L)) {
                    list.add(config);
                }
            }
        }
        return ResultDTO.buildSuccessResult(list);
    }

    @ApiOperation("竞价订单回调")
    @PostMapping("/order/callback")
    public ResultDTO orderCallBack(@RequestBody AuctionOrderDTO auctionOrderDTO){
        List<OrderCallBackDTO> result = auctionOrderService.orderCallBack(auctionOrderDTO.getOrderIds());
        return ResultDTO.buildSuccessResult(result);
    }

    @ApiOperation("竞价发放奖品优惠券")
    @PostMapping("/send/coupon")
    public ResultDTO sendCoupon(@RequestBody AuctionOrderDTO auctionOrderDTO){
        auctionOrderService.sendCoupon(auctionOrderDTO);
        return ResultDTO.buildEmptySuccess();
    }

    @ApiOperation("发送站内信")
    @PostMapping("/send/notice")
    public ResultDTO sendNotice(@RequestBody TzySysNoticeRecord noticeRecord){
        noticeRecord.setFromUser("HOBBY STOCKS");
        noticeRecord.setType(NoticeType.ACT);
        int rs = noticeRecordService.insertTzySysNoticeRecord(noticeRecord);
        if(rs == 0){
            return ResultDTO.build500Error("竞价发送站内信失败:" + noticeRecord.getToUserid());
        }
        return ResultDTO.buildEmptySuccess();
    }

    @ApiOperation("发送极光推送")
    @PostMapping("/send/jPush")
    public ResultDTO jPush(@RequestBody AuctionJPushDTO auctionJPushDTO) {
        List<String> smsRegisterList = mineApiService.searchUserInfoByIds(auctionJPushDTO.getUserIds()).stream()
                .filter(appUserInfoDto -> Objects.nonNull(appUserInfoDto) && !StringUtils.isEmpty(appUserInfoDto.getSmsRegisterId()))
                .map(AppUserInfoDto::getSmsRegisterId)
                .distinct()
                .collect(Collectors.toList());
        Map<String, String> extrasMap = new HashMap<>();
        extrasMap.put("url", auctionJPushDTO.getUrl());
        asyncAppService.jpush(19, Constants.JPUSH_TYPE_ID, smsRegisterList, auctionJPushDTO.getParams(), extrasMap);
        return ResultDTO.buildEmptySuccess();
    }

    @ApiOperation("竞价积分变更")
    @PostMapping("/change/point")
    public ResultDTO changePoint(@RequestBody UserPointDTO userPointDTO){
        if (userPointDTO == null || userPointDTO.getPointRecords() == null) {
            return ResultDTO.build500Error("参数为空");
        }

        userPointDTO.getPointRecords().forEach(record ->{
            Long point = record.getChangePoint();
            if(point < 0){
                AppBaseUser appBaseUser = appBaseUserService.selectAppBaseUserById(userPointDTO.getUserId().longValue());
                if(appBaseUser == null) {
                    throw new ServiceException("用户不存在");
                }
                // 负数，检查积分是否足够
                long pointsToDeduct = Math.abs(point); // 获取要扣除的积分值
                if(appBaseUser.getPoint() < pointsToDeduct){
                    throw new ServiceException("积分不足");
                }
            }

            record.setType(Constants.POINT_TYPE_COMMON)
                    .setChangePoint(record.getChangePoint())
                    .setUserId(userPointDTO.getUserId().longValue())
                    .setOrderId(record.getOrderId())
                    .setOrderNo("抢拍活动")
                    .setRefId(record.getRefId())
                    .setCreateTime(new Date());
        });
        mineApiService.addPointsOfUser(userPointDTO.getUserId(), userPointDTO.getPointRecords());
        return ResultDTO.buildEmptySuccess();
    }

    @ApiOperation("竞价下单")
    @PostMapping("/order/submit")
    public ResultDTO orderSubmit(@RequestBody AuctionOrderDTO auctionOrderDTO){
        OrderSubmitDTO orderSubmitDTO = auctionOrderService.generateOrder(auctionOrderDTO);
        return ResultDTO.buildSuccessResult(orderSubmitDTO);
    }

    @ResponseBody
    @GetMapping(value = "/group/info/{id}")
    //@ApiVersion(1.0)
    @ApiOperation("获取组队信息")
    public CardGroupInfoDTO getGroupInfo(@PathVariable("id") Long id) {
        CardGroupInfoDTO info=new CardGroupInfoDTO();
        info.setId(id);
        return suidRich.selectOne(info);
    }

    @ResponseBody
    @GetMapping(value = "/order/detail/{id}")
    //@ApiVersion(1.0)
    @ApiOperation("获取组队信息")
    public OrderDTO getOrderDetail(@PathVariable("id") Long id) {
        OrderDTO order=new OrderDTO();
        order.setId(id);
        order=suidRich.selectOne(order);
        OrderListDTO condition=new OrderListDTO();
        condition.setOrderId(id);
        List<OrderListDTO> orderLists = suidRich.select(condition);
        if(!orderLists.isEmpty()){
            List<GoodsListDTO> list = orderLists.stream().filter(ol -> ol.getStatus()==100||ol.getStatus()==101)
                    .map(ol -> new GoodsListDTO(ol.getQty(), ol.getSkuId(), ol.getSkuName())).collect(Collectors.toList());
            order.setGoodsListDTOS(list);
        }
        return order;
    }

    @ResponseBody
    //@PostMapping(value = "/order/allocate/callback")
    //@ApiVersion(1.0)
    @ApiOperation("卡密分配后回调")
    public ResultDTO orderAllocateCallBack(@RequestBody AllocateResult result) {
        if(result.getOrderId()==null){
            return ResultDTO.buildErrorResult("参数缺失");
        }
        CardGroupOrderInfo order = new CardGroupOrderInfo();
        order.setId(result.getOrderId());
        CardGroupOrderInfo existOrder = suidRich.selectOne(order);
        if(existOrder == null){
            return ResultDTO.buildErrorResult("订单不存在");
        }
        order.setGoodsAllocate(1);
        order.setProp2(result.getGuessCount()>0?result.getGuessCount().toString():"0");
        order.setProp3(result.getMissCardCount()>0?result.getMissCardCount().toString():"0");
        order.setUpdateTime(DateUtils.getTimestampNow());
        suidRich.update(order);
        allocateGoodsService.aftAllocateOrderGoods(existOrder.getGroupInfoId());
        return ResultDTO.buildEmptySuccess();
    }

    @ResponseBody
    @GetMapping(value = "/public/{actId}")
    @ApiOperation("公布抽奖码")
    public ResultDTO publicActCode(@PathVariable("actId") Integer actId, @RequestParam String code) {
        String key="app_lucky_public_code_"+actId;
        if(redisUtils.hasKey(key)){
            return ResultDTO.buildErrorResult("短时间内请勿重复请求!");
        }
        log.info("接收到抽奖结果公布回调:活动id:{},code:{}",actId,code);
        redisUtils.set(key,1,60);
        List<PublicCodeResultDTO> resultDTOs = appActService.publicActCode(new PublicCodeParam(actId, code, null));
        for (PublicCodeResultDTO resultDTO : resultDTOs) {
            appActService.sendWinCodesPrize(resultDTO.getWinCodes(),resultDTO.getPrize());
            String failMsg=String.format(NoticeMsgModel.LUCKY_ACT_FAIL_NOTICE, resultDTO.getPrize().getName());
            //禁用发放默认奖品功能
//            if(StringUtils.isNotEmpty(resultDTO.getDefaultPrizeConfig())){
//                JSONObject prizeJson = JSON.parseObject(resultDTO.getDefaultPrizeConfig());
//                failMsg=String.format(NoticeMsgModel.LUCKY_ACT_DEFAULT_PRIZE_NOTICE, resultDTO.getPrize().getName(),prizeJson.getString("name"));
//                Integer prizeId = prizeJson.getInteger("prizeId");
//                appActService.sendActDefaultCoupon(actId,prizeId);
//            }
            asyncAppService.noticeActUser(actId,2,failMsg, "活动揭晓记录",resultDTO.getActType());
        }

        redisUtils.del(key);
        return ResultDTO.buildEmptySuccess();
    }


    @ApiLog(title = "重新申请抽奖码", businessType = BusinessType.SEARCH)
    @ResponseBody
    @PostMapping(value = "/luck/code/repeat/{userId}/{prizeRecordId}")
    //@ApiVersion(1.0)
    @ApiOperation("重新申请抽奖码")
    public OutDTO repeat(@PathVariable("userId") Integer userId,@PathVariable("prizeRecordId") Integer prizeRecordId) {
        if (prizeRecordId == null || userId == null) {
            return OutDTO.error500("参数未传!");
        }
        appActService.checkLuckyCode(prizeRecordId, userId);
        return OutDTO.ok();
    }

    @ResponseBody
    @GetMapping(value = "/group/living/check/{id}")
    @ApiOperation("拼团是否允许直播")
    public ResultDTO allowedStartGroupLive(@PathVariable("id") Integer groupInfoId) {
        GroupInfo groupInfo = groupApiService.getGroupInfoById(groupInfoId);
        AppAssert.notNull(groupInfo, "拼团不存在!");
        return ResultDTO.buildSuccessResult(groupApiService.allowedStartGroupLive(groupInfo));
    }

    @PostMapping("/merchant/avatars")
    @ApiOperation("官网商家头像")
    public ResultDTO getMerchantAvatars(@RequestBody MerchantAvatarsDTO merchantAvatars){
        PageInfo<String> avatars = tzyMerchantInfoService.getAvatars(merchantAvatars);
        return ResultDTO.buildSuccessResult(avatars);
    }

//    /**
//     * 根据id集合查询拼团信息
//     */
//    @ResponseBody
//    @GetMapping(value = "/groupInfoByIds")
//    @ApiOperation("根据id集合查询拼团信息")
//    public ResultDTO getGroupInfoByIds(@RequestParam("ids") String ids) {
//        List<Integer> groupInfoIds = Arrays.stream(ids.split(",")).map(Integer::parseInt).collect(Collectors.toList());
//        List<ProductPromGroupInfoDto> groupInfos = groupApiService.getGroupInfosByIds(groupInfoIds);
//        return ResultDTO.buildSuccessResult(groupInfos);
//    }


    /**
     * 获取店铺基本信息
     *
     * @return
     */
    @ApiLog(title = "根据id获取店铺基本信息", businessType = BusinessType.SEARCH, indto = "{{inDto}}")
    @ResponseBody
    @RequestMapping(value = "/getMerchantInfoByID", method = RequestMethod.POST)
    public OutDTO getMerchantBasicInfoByID(@RequestBody InDto inDto) {
        if (null == inDto) {
            return OutDTO.error(10000, "参数不能为空");
        }
        Object idObj = inDto.get("id");
        if (null == idObj) {
            return OutDTO.error(10010, "参数[id]不能为空");
        }
        int targetMerId = Integer.parseInt(idObj.toString());
        //查询商家信息
        MerchantInfo merchantInfo = merchantApiService.getMerchantInfo(targetMerId);
        if (null == merchantInfo) {
            return OutDTO.error500("商家不存在");
        }
        return OutDTO.ok()
                .put("merchantInfo", merchantInfo);
    }

    /**
     * 根据id集合查询拼团状态信息
     */
    @ResponseBody
    @PostMapping(value = "/groupInfoStatus")
    @ApiOperation("根据id集合查询拼团信息")
    public ResultDTO getGroupInfoStatus(@RequestBody List<Integer> editGroupIds) {
        if (editGroupIds == null || editGroupIds.isEmpty()) {
            return ResultDTO.buildErrorResult("参数为空!");
        }
        if (editGroupIds.size()>30) {
            return ResultDTO.buildErrorResult("最多只能查询30条!");
        }
        List<GroupStatusInfoDto> groupInfos = groupApiService.getGroupStatusByIds(editGroupIds);
        return ResultDTO.buildSuccessResult(groupInfos);
    }

    /**
     * 统计打款信息
     */
    @ResponseBody
    @PostMapping(value = "/generateGroupPaymentRecord")
    @ApiOperation("统计打款信息")
    public ResultDTO generateGroupClosePaymentRecord(@RequestBody Integer groupIds) {
        if (groupIds == null) {
            return ResultDTO.buildErrorResult("参数为空!");
        }
        cardGroupInfoService.checkAllActClosePaymentInfosWithoutChannel(groupIds);
        return ResultDTO.buildSuccessResult("success");
    }

    /**
     * 根据id集合查询拼团状态信息
     */
    @ResponseBody
    @PostMapping(value = "/orderInfoStatus")
    @ApiOperation("根据id集合查询拼团信息")
    public ResultDTO getGroupOrderInfoStatus(@RequestBody List<Long> orderIds) {
        if (orderIds == null || orderIds.isEmpty()) {
            return ResultDTO.buildErrorResult("参数为空!");
        }
        if (orderIds.size()>30) {
            return ResultDTO.buildErrorResult("最多只能查询30条!");
        }
        List<OrderStatusDTO> groupInfos = cardGroupOrderInfoService.getOrderInfoStatus(orderIds);
        return ResultDTO.buildSuccessResult(groupInfos);
    }
    @ApiLog(title = "更新个人资料",businessType = BusinessType.SEARCH,indto = "{{inDto}}")
    @ResponseBody
    @PostMapping(value = "/user/inviteCode")
    public ResultDTO getInviteCode(@RequestBody List<Long> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return ResultDTO.buildErrorResult("参数为空!");
        }
        if (userIds.size()>100) {
            return ResultDTO.buildErrorResult("最多只能查询100条!");
        }
        //循环用户信息
        for (Long userId : userIds) {
            appUserDetailInfoService.getByUserId(userId.intValue());
        }
        return ResultDTO.buildSuccessResult(userIds.size());
    }
    @ResponseBody
    @GetMapping("/guess/prize/{teamId}")
    @ApiOperation("竞猜活动中奖用户自动参与区块链")
    public ResultDTO guessPrize(@PathVariable("teamId")Long teamId){
        try {
            appActService.guessSendPrize(teamId);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDTO.build500Error(e.getLocalizedMessage());
        }
        return ResultDTO.buildEmptySuccess();
    }
}
