package com.cyksj.web.controller.register;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cyksj.common.annotation.NoSubmit;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.IoKit;
import com.cyksj.common.util.Xmls;
import com.cyksj.dto.Result;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.AppleAutoRegisterDataMapper;
import com.cyksj.mapper.ProxysMapper;
import com.cyksj.mapper.manage.coupon.CouponSkuMapper;
import com.cyksj.model.dto.H5JsPayParams;
import com.cyksj.model.entity.AppleAutoRegisterData;
import com.cyksj.model.entity.Proxys;
import com.cyksj.model.entity.RegisterOrderDon;
import com.cyksj.model.entity.SpotifyUnLimitRecord;
import com.cyksj.model.manage.request.RegisterReq;
import com.cyksj.model.request.AlipayOrderDonReq;
import com.cyksj.model.response.AliPayTradeStatus;
import com.cyksj.model.views.AppleIdCountryOrAreaDataView;
import com.cyksj.model.views.CouponUserView;
import com.cyksj.service.register.RegisterOrderDonService;
import com.cyksj.service.user.UserBindRelationService;
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.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author chan
 * @date 2022/11/7 1:49 PM
 */
@Slf4j
@RestController
@RequestMapping("/applets/register")
@RequiredArgsConstructor
public class RegisterController {

    private final RegisterOrderDonService registerOrderDonService;

    private final BeanSearcher beanSearcher;

    private final HttpServletRequest request;

    private final AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;

	private final ProxysMapper proxysMapper;

    private final CouponSkuMapper couponSkuMapper;

    private final UserBindRelationService userBindRelationService;

    @PostMapping
    public Result<RegisterOrderDon> register(@RequestBody RegisterReq req) throws Exception {
        long userId = StpUserUtil.getLoginIdAsLong();
        //参数校验
        boolean isFree = false;
        //判断Spotify是否拥有免费资格
        if("spotify".equals(req.getPlatform())){
            isFree = registerOrderDonService.isFree(userId,req.getPlatform(),req.getCode());
        }
        RegisterOrderDon orderDon = registerOrderDonService.saveOrder(userId,req,isFree);

        orderDon.setPassword("");

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

  /**
   * 注册资料支付
   * @author chan
   * @date 2022-11-07 3:44 PM
   */
    @PostMapping("/post/pay/{orderId}")
    public Result<H5JsPayParams> pay(@PathVariable Long orderId) throws Exception {
        final String methodName = "提交注册资料 吊起微信支付";
        log.info("{}[start] orderId:{}",methodName,orderId);

        H5JsPayParams payParams = registerOrderDonService.pay(orderId);

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

    /**
     * 微信支付回调
     * @author chan
     * @date 2021-10-11 下午5:42
     */
    @PostMapping("/prepay/notify")
    public void prepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String xml = IoKit.toString(request.getInputStream());
        log.info("=== 微信支付成功的回调: \n {}", xml);

        // 解析xml
        Map<String, String> map = Xmls.toMap(xml);

        // 支付失败
        if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) {
            throw BusinessRuntimeException.getInstance("支付失败.");
        }

        registerOrderDonService.prepayNotify(map);
        String toWeChatXmlResponse = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

        OutputStream out = null;
        try {
            out = response.getOutputStream();
            IoKit.write(toWeChatXmlResponse, out);
        } catch (Exception e) {
            throw BusinessRuntimeException.getInstance(e,e.getMessage());
        } finally {
            IoKit.close(out);
        }
    }

    /**
     * 支付宝支付
     */
    @PostMapping("/zfb/unified/pay")
    public Result<String> zfbUnifiedPay(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
        if (re.getType() == null) throw BusinessRuntimeException.getInstance("支付异常");
        String pay_body = registerOrderDonService.zfbUnifiedPay(re).getBody();
//        response.setContentType("text/html;charset=" + BaseZfbConfig.charset);
//        //直接将完整的表单html输出到页面
//        response.getWriter().write(pay_body);
//        response.getWriter().flush();
//        response.getWriter().close();
        return GatewayResponse.SUCCESS.newBuilder().toResult(pay_body);
    }

    /**
     * 支付宝回调
     */
    @PostMapping("/prepay/zfb/notify")
    public String aliPayNotify(HttpServletRequest request) throws Exception {
        ////将异步通知中收到的所有参数都存放到map中
        Map<String, String> params = convertRequestParamsToMap(request);
        String tradeStatus = params.get("trade_status");
        String orderNo = params.get("out_trade_no");
        if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) {
            log.info("支付宝商家订单号orderNo:{},status:{}开始回调", orderNo, tradeStatus);
            registerOrderDonService.aliPayNotify(params);
        } else {
            log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
            return "fail";
        }
        return "success";
    }

    @GetMapping("/get")
    public Result<SearchResult<RegisterOrderDon>> get(){
        long userId = StpUserUtil.getLoginIdAsLong();
        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
        SearchResult<RegisterOrderDon> search = beanSearcher.search(RegisterOrderDon.class, MapUtils.flatBuilder(request.getParameterMap())
                .field(RegisterOrderDon::getUserId, userIdList).op(Operator.InList)
                .build());
        search.getDataList().forEach(data->{
            if (data.getAppleIsAutoType() && (data.getStatus() == RegisterOrderDon.Status.noPayment || data.getStatus() == RegisterOrderDon.Status.close)) {
                data.setApplePwdId(null);
                data.setCountryOrArea(null);
                data.setRemark(null);
            }
        });
        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
    }

    @GetMapping("/get/status/{orderId}")
    public Result<RegisterOrderDon> getOrderStatusById(@PathVariable Long orderId) {
        long userId = StpUserUtil.getLoginIdAsLong();
        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
        RegisterOrderDon registerOrderDon = beanSearcher.searchFirst(RegisterOrderDon.class, MapUtils.flatBuilder(request.getParameterMap())
                .field(RegisterOrderDon::getUserId, userIdList).op(Operator.InList)
                .field(RegisterOrderDon::getId, orderId)
                .selectExclude(RegisterOrderDon::getApplePwdId, RegisterOrderDon::getCountryOrArea, RegisterOrderDon::getRemark)
                .build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(registerOrderDon);
    }

    @PutMapping("/put")
    public Result<String> update(@RequestBody RegisterOrderDon req){
        if (req.getId() == null) {
            throw new BusinessRuntimeException("缺少必填参数");
        }
        RegisterOrderDon registerOrderDon = registerOrderDonService.getById(req.getId());
        if (!registerOrderDon.getStatus().equals(RegisterOrderDon.Status.error)) {
            throw new BusinessRuntimeException("该状态下不可更改信息");
        }
        req.setStatus(RegisterOrderDon.Status.hasPayment);
        registerOrderDonService.updateById(req);

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

    @GetMapping("/get/appleId/area/detail")
    public Result<AppleIdCountryOrAreaDataView> getAppleIdCountryOrAreaData() {
        AppleIdCountryOrAreaDataView appleIdCountryOrAreaDataView = new AppleIdCountryOrAreaDataView();
        appleIdCountryOrAreaDataView.setJapanAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.JAPAN));
        appleIdCountryOrAreaDataView.setHongKongAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.CN_HongKong));
        appleIdCountryOrAreaDataView.setUsAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.US));
        appleIdCountryOrAreaDataView.setTaiWanAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.CN_TaiWan));
        return GatewayResponse.SUCCESS.newBuilder().toResult(appleIdCountryOrAreaDataView);
    }

    /**
     * 取消appleId订单
     */
    @PutMapping("/cancel/order/{orderId}")
    public Result<String> cancelOrder(@PathVariable Long orderId) {
        registerOrderDonService.updateAppleAutoStatus(orderId);
        return GatewayResponse.SUCCESS.newBuilder().toResult("取消订单成功");
    }

    /**
     * 解除限制申请
     */
    @PostMapping("/spotify/unLimit")
    @NoSubmit
    public Result<CouponUserView> spotifyUnLimit(@RequestBody @Validated SpotifyUnLimitRecord spotifyUnLimitRecord) {
        long userId = StpUserUtil.getLoginIdAsLong();
        spotifyUnLimitRecord.setUserId(userId);
        CouponUserView couponUserView = registerOrderDonService.spotifyUnLimit(spotifyUnLimitRecord);
        if (couponUserView != null) {
            String str = couponSkuMapper.selectGoodsSkuStr(couponUserView.getCouponId());
            couponUserView.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult(couponUserView);
    }

    /**
     * 查询是否有可用的spotify年付优惠券
     */
    @GetMapping("/get/available/spotifyCoupon")
    public Result<CouponUserView> getAvailableSpotifyCoupon() {
        CouponUserView couponUserView = registerOrderDonService.getAvailableSpotifyCoupon(StpUserUtil.getLoginIdAsLong());
        if (couponUserView != null) {
            String str = couponSkuMapper.selectGoodsSkuStr(couponUserView.getCouponId());
            couponUserView.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult(couponUserView);
    }

    /**
     * 获取代理ip
     */
    @GetMapping("/get/proxys")
    public Result<Page<Proxys>> getProxys(@RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "10") Integer limit) {
        return GatewayResponse.SUCCESS.newBuilder().toResult(proxysMapper.selectPage(new Page<>(start, limit), Wrappers.lambdaQuery(Proxys.class).orderByDesc(Proxys::getScore)));
    }

    /**
     * 获取支付宝回调参数
     */
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<>();
        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;
            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.substring(1));
            } else {
                retMap.put(name, "");
            }
        }
        return retMap;
    }

}
