package com.cyksj.web.controller.user;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.annotation.NoSubmit;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.dto.Result;
import com.cyksj.enums.GatewayApiCode;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.OrderDonMapper;
import com.cyksj.mapper.manage.coupon.CouponUserMapper;
import com.cyksj.model.dto.UserWhoami;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.views.GroupsRelationView;
import com.cyksj.model.request.*;
import com.cyksj.model.response.UserAuthLoginResp;
import com.cyksj.model.views.*;
import com.cyksj.service.corp.CorpInteractiveReaderFrontService;
import com.cyksj.service.corp.CropChatService;
import com.cyksj.service.exchange.ExchangeCodeService;
import com.cyksj.service.order.UserRealOrderBenefitsService;
import com.cyksj.service.shop.YhShopFrontService;
import com.cyksj.service.user.UserBindRelationService;
import com.cyksj.service.user.UserService;
import com.cyksj.service.user.WorkOrderFrontService;
import com.cyksj.web.util.StpUserUtil;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapBuilder;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author chan
 * @date 2021/10/11 下午11:05
 */
@RequestMapping("/applets/user")
@RestController
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    private final ExchangeCodeService exchangeCodeService;

    private final CouponUserMapper couponUserMapper;

    private final OrderDonMapper orderDonMapper;

    private final UserRealOrderBenefitsService userRealOrderBenefitsService;

    private final BeanSearcher beanSearcher;

    private final WorkOrderFrontService workOrderFrontService;

    private final HttpServletRequest request;

    private final CropChatService cropChatService;

    private final UserBindRelationService userBindRelationService;

    private final YhShopFrontService yhShopFrontService;

    private final CorpInteractiveReaderFrontService corpInteractiveReaderFrontService;

    @GetMapping(value = "/wx/whoami")
    public Result<UserWhoami> whoami() {
        long userId = StpUserUtil.getLoginIdAsLong();

        UserWhoami userWhoami = userService.whoami(userId);

        return GatewayResponse.SUCCESS.newBuilder().toResult(userWhoami);
    }

    /**
     * 兑换码兑换车票
     */
    @PostMapping("/get/ticket")
    public Result<String> getTicketByExchangeCode(@RequestBody ExchangeCodeTicket exchangeCodeTicket) {
        Long userId = StpUserUtil.getLoginIdAsLong();
        return exchangeCodeService.getTicketByExchangeCode(exchangeCodeTicket, userId);
    }

    /**
     * 个人中心详情
     */
    @GetMapping("/personal")
    public Result<UserPersonalView> getPersonalView(String customId) {
        long userId = StpUserUtil.getLoginIdAsLong();
        List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
        List<RenewalView> renewalViews = beanSearcher.searchAll(RenewalView.class, builder
                .field(RenewalView::getUserId, 0).op(Operator.GreaterThan)
                .field(RenewalView::getUserId, userIds).op(Operator.InList)
                .field(RenewalView::getStatus, List.of("validity", "overdue", "outside")).op(Operator.InList)
                .orderBy(RenewalView::getExpiryTime).asc()
                .onlySelect(RenewalView::getExpiryTime)
                .build());
        DateTime now = DateTime.now();
        renewalViews = renewalViews.stream().filter(e -> {
            if (e.getExpiryTime() != null && e.getExpiryTime().before(now)) {
                return false;
            }
            return true;
        }).collect(Collectors.toList());
        UserPersonalView personalView = new UserPersonalView();
        //车票
        personalView.setNumOfTickets(renewalViews.size());
        //优惠券
        Integer couponSize = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
                .eq(CouponUser::getUserId, userId)
                .eq(CouponUser::getStatus, CouponUser.Status.unused)
                .le(CouponUser::getValidStartTime, now)
                .gt(CouponUser::getValidEndTime, now));
        personalView.setNumOfCoupons(couponSize);
        //积分
        User user = userService.getById(userId);
        personalView.setActivePoints(user.getActivePoints());
        //推广积分
        personalView.setPopularizePoints(user.getPoints());
        personalView.setBalance(user.getBalance());
        OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
                .eq(OrderDon::getUserId, userId)
                .eq(OrderDon::getStatus, OrderDon.Status.noPayment).last("limit 1"));
        personalView.setIsNoPayment(orderDon != null ? true : false);
        //礼品卡可用数量
        Number numOfGiftCard = beanSearcher.searchCount(GiftCardUserRecordView.class, MapUtils.builder()
                .put("uid", String.format("((user_id = %s and is_send = 0) or (to_user_id = %s and is_used = 0))", userId, userId))
                .field(GiftCardUserRecordView::getIsPay, true)
                .build());
        personalView.setNumOfGiftCard(numOfGiftCard.intValue());
        return GatewayResponse.SUCCESS.newBuilder().toResult(personalView);
    }

    /**
     * 用户已有实物权益 可选车票
     */
    @GetMapping("/get/available/benefits/tickets")
    public Result<List<UserAvailableGoodsTicketView>> getAvailableBenefitsTickets(Long orderId, String customId) {
        Long userId = StpUserUtil.getLoginIdAsLong();
        Long yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
        List<UserAvailableGoodsTicketView> tickets = userRealOrderBenefitsService.getAvailableBenefitsTickets(userId, orderId, yhsId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(tickets);
    }

    /**
     * 用户领取实物权益
     */
    @PostMapping("/receive/benefits")
    public Result<List<GroupsRelationView>> receiveRealGoodsBenefits(@RequestBody List<ReceiveBenefitsReq> reqList) {
        List<GroupsRelationView> re = new ArrayList<>();
        Long userId = StpUserUtil.getLoginIdAsLong();
        reqList.forEach(req -> {
            Long benefitsId = req.getBenefitsId(), goodsId = req.getGoodsId(), skuId = req.getSkuId(), relationId = req.getRelationId();
            Assert.notNull(benefitsId, "可获取的权益不存在");
            Assert.notNull(goodsId, "请选择对应平台");
            Assert.notNull(skuId, "请选择对应权益规格");
            Assert.notNull(relationId, "请选择对应车票");
            GroupsRelationView groupsRelationView = userRealOrderBenefitsService.receiveRealGoodsBenefits(userId, benefitsId, goodsId, skuId, relationId);
            re.add(groupsRelationView);
        });
        return GatewayResponse.SUCCESS.newBuilder().toResult(re);
    }

    /**
     * 用户提交工单
     */
    @PostMapping("/workOrder/submit")
    @NoSubmit
    public Result<String> submitWorkOrder(@RequestBody @Validated WorkOrderReq workOrderReq) {
        long userId = StpUserUtil.getLoginIdAsLong();
        workOrderReq.setUserId(userId);
        workOrderFrontService.submitWorkOrder(workOrderReq);
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 用户工单历史列表
     */
    @GetMapping("/workOrder/get")
    public Result<SearchResult<UserWorkOrderView>> getWorkOrder(String customId) {
        Long yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
        long userId = StpUserUtil.getLoginIdAsLong();
        SearchResult<UserWorkOrderView> search = beanSearcher.search(UserWorkOrderView.class, MapUtils.flatBuilder(request.getParameterMap())
                .field(UserWorkOrderView::getUserId, userId)
                .field(UserWorkOrderView::getYhsId, yhsId)
                .orderBy(UserWorkOrderView::getCreatedTime).desc()
                .build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
    }

    /**
     * 用户工单详情
     */
    @GetMapping("/workOrder/get/detail/{id}")
    public Result<SearchResult<WorkOrderChatHistoryView>> getWorkOrderDetails(@PathVariable Long id) {
        long userId = StpUserUtil.getLoginIdAsLong();
        SearchResult<WorkOrderChatHistoryView> search = beanSearcher.search(WorkOrderChatHistoryView.class, MapUtils.builder()
                .field(WorkOrderChatHistoryView::getUserId, userId)
                .field(WorkOrderChatHistoryView::getWorkOrderId, id)
                .orderBy(WorkOrderChatHistoryView::getId).desc()
                .selectExclude(WorkOrderChatHistoryView::getReplyCustomerServiceId,
                        WorkOrderChatHistoryView::getCustomer)
                .build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
    }

    /**
     * 工单状态查询
     */
    @GetMapping("/workOrder/get/status/{id}")
    public Result<WorkOrder> getWorkOrderStatus(@PathVariable Long id) {
        long userId = StpUserUtil.getLoginIdAsLong();
        WorkOrder workOrder = beanSearcher.searchFirst(WorkOrder.class, MapUtils.builder()
                .field(WorkOrder::getUserId, userId)
                .field(WorkOrder::getId, id)
                .onlySelect(WorkOrder::getId, WorkOrder::getUserId, WorkOrder::getStatus)
                .build());
        if (workOrder == null) {
            throw BusinessRuntimeException.getInstance("该工单不存在");
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult(workOrder);
    }


    /**
     * 用户回复客服
     */
    @PostMapping("/workOrder/reply")
    public Result<String> userReplyWorkOrder(@RequestBody @Validated WorkOrderChatHistory history) {
        long userId = StpUserUtil.getLoginIdAsLong();
        history.setUserId(userId);
        workOrderFrontService.replyCustomer(history);
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 修改用户信息
     */
    @PutMapping("/update/userInfo")
    public Result<String> updateHeadImg(@RequestBody UserReq request) {
        long userId = StpUserUtil.getLoginIdAsLong();
        User user = userService.getById(userId);
        if (user == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
        Boolean isFlag = false;
        if (StrUtil.isNotBlank(request.getNickname())) {
            if (request.getNickname().length() > 32) {
                throw BusinessRuntimeException.getInstance("名称过长");
            }
            user.setNickname(request.getNickname());
            isFlag = true;
        }
        if (request.getSex() != null) {
            user.setSex(request.getSex());
            isFlag = true;
        }
        if (StrUtil.isNotBlank(request.getHeadimgurl())) {
            user.setHeadimgurl(request.getHeadimgurl());
            isFlag = true;
        }
        if (isFlag) {
            userService.updateById(user);
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 更新用户最后一次登录时间
     */
    @PutMapping("/update/lastTime")
    public Result<String> updateLastTime() {
        long userId = StpUserUtil.getLoginIdAsLong();
        User user = userService.getById(userId);
        if (user == null) {
            return GatewayResponse.SUCCESS.newBuilder().toResult();
        }
        user.setLastTime(DateTime.now());
        userService.updateById(user);
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 查看用户所有余额
     */
    @GetMapping("/get/balance")
    public Result<User> getUserBalance() {
        long userId = StpUserUtil.getLoginIdAsLong();
        User user = userService.getOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getId, userId)
                .select(User::getNickname, User::getBalance)
                .last("limit 1"));
        return GatewayResponse.SUCCESS.newBuilder().toResult(user);
    }

    /**
     * 获取群聊二维码
     */
    @GetMapping("/get/corp/ChatCode/{goodsId}")
    public Result<String> getCorpChatCode(@PathVariable Long goodsId) throws Exception {
        long userId = StpUserUtil.getLoginIdAsLong();
        //获取对应产品的企业微信客户群
        String qrCode = cropChatService.getCropWxChatGroupByGoodsId(goodsId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(qrCode);
    }

    /**
     * 获取奈飞客服活码弹窗
     */
    @GetMapping("/get/corp/serviceCode/{goodsId}")
    public Result<String> getCorpServiceCode(@PathVariable Long goodsId) {
        long userId = StpUserUtil.getLoginIdAsLong();
        String qrCode = cropChatService.getCorpServiceCode(goodsId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(qrCode);
    }

    /**
     * 用户账号关联列表
     */
    @GetMapping("/get/userAccounts")
    public Result<List<UserBindAccountView>> getUserBindAccountViews() {
        long userId = StpUserUtil.getLoginIdAsLong();
        List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
        List<UserBindAccountView> accountViews = beanSearcher.searchAll(UserBindAccountView.class, MapUtils.builder().field(UserBindAccountView::getUserId, relationUserIdList)
                .op(Operator.InList)
                .build());
        if (relationUserIdList.size() > 1) {
            for (UserBindAccountView accountView : accountViews) {
                if (accountView.getUserId().equals(userId)) {
                    accountViews.remove(accountView);
                    accountViews.add(0, accountView);
                    break;
                }
            }
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult(accountViews);
    }

    /**
     * 切换账号
     */
    @PutMapping("/switch/account")
    public Result<UserAuthLoginResp> switchOtherAccount(@RequestBody UserBindAccountView request) {
        long userId = StpUserUtil.getLoginIdAsLong();
        Long switchUserId = request.getUserId();
        List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
        if (!relationUserIdList.contains(switchUserId)) {
            throw BusinessRuntimeException.getInstance("切换账号异常,请刷新页面重试");
        }
        User switch_user = userService.getById(switchUserId);
        Assert.notNull(switch_user, "切换的账号不存在");
        StpUserUtil.login(switch_user.getId());
        UserAuthLoginResp loginPhoneRep = new UserAuthLoginResp(StpUserUtil.getTokenValue(), switch_user.getShowId(), switch_user.getNickname(), switch_user.getHeadimgurl());
        return GatewayResponse.SUCCESS.newBuilder().toResult(loginPhoneRep);
    }

    /**
     * 个人礼品卡列表
     * @return
     */
    @GetMapping("/get/giftCard")
    public Result<SearchResult<GiftCardUserPayFrontView>> getGiftCard() {
        long userId = StpUserUtil.getLoginIdAsLong();
        String condition = String.format("and (user_id = %s or to_user_id = %s)", userId, userId);
        SearchResult<GiftCardUserPayFrontView> view = beanSearcher.search(GiftCardUserPayFrontView.class, MapUtils.builder()
                .put("condition", condition)
                .put("uid", userId)
                .orderBy(GiftCardUserRecordView::getIsUsed).asc()
                .orderBy(GiftCardUserPayFrontView::getId).desc().build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(view);
    }

    /**
     * 可用现金礼品卡列表
     */
    @GetMapping("/get/available/giftCard")
    public Result<List<GiftCardUserPayFrontView>> getAvailGiftCard() {
        long userId = StpUserUtil.getLoginIdAsLong();
        String condition = String.format("and to_user_id = %s", userId);
        List<GiftCardUserPayFrontView> view = beanSearcher.searchAll(GiftCardUserPayFrontView.class, MapUtils.builder()
                .put("condition", condition)
                .put("uid", userId)
                //现金卡
                .field(GiftCardUserPayFrontView::getGcType, 1)
                .orderBy(GiftCardUserRecordView::getIsUsed).asc()
                .orderBy(GiftCardUserPayFrontView::getId).desc().build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(view);
    }

    /**
     * 礼品卡分享详情
     */
    @GetMapping("/get/giftCard/detail/{code}")
    public Result<GiftCardDetailFrontView> getGiftCardDetailByCode(@PathVariable String code) {
        GiftCardDetailFrontView detail = beanSearcher.searchFirst(GiftCardDetailFrontView.class, MapUtils.builder().field(GiftCardDetailFrontView::getCode, code).build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(detail);
    }

    /**
     * 领取他人礼品卡
     */
    @PostMapping("/receive/giftCard")
    public Result<String> receiveGiftCardByRc(@RequestBody GiftCardReceiveReq req) {
        long userId = StpUserUtil.getLoginIdAsLong();
        Long relationId = req.getRelationId();
        userService.receiveGiftCardByRc(userId, req.getCode(), relationId);
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 点击雷达链接
     */
    @PostMapping("/click/reader/{radarId}")
    public Result<String> clickInteractiveReader(@PathVariable Long radarId) throws Exception {
        long userId = StpUserUtil.getLoginIdAsLong();
        corpInteractiveReaderFrontService.clickReader(userId, radarId);
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

}
