package com.slodon.b2b2c.controller.member.front;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.slodon.b2b2c.core.constant.MemberWithdrawConst;
import com.slodon.b2b2c.core.constant.PayConst;
import com.slodon.b2b2c.core.controller.BaseController;
import com.slodon.b2b2c.core.exception.MallException;
import com.slodon.b2b2c.core.response.JsonResult;
import com.slodon.b2b2c.core.response.PageVO;
import com.slodon.b2b2c.core.response.PagerInfo;
import com.slodon.b2b2c.core.response.SldResponse;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.core.util.UserUtil;
import com.slodon.b2b2c.core.util.WebUtil;
import com.slodon.b2b2c.member.example.MemberBankAccountExample;
import com.slodon.b2b2c.member.pojo.Member;
import com.slodon.b2b2c.member.pojo.MemberBankAccount;
import com.slodon.b2b2c.model.member.MemberBankAccountModel;
import com.slodon.b2b2c.vo.member.MemberBankAccountVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author slodon
 */
@Api(tags = "front-提现账号管理")
@Slf4j
@RestController
@RequestMapping("v3/member/front/member/cash")
public class FrontMemberCashController extends BaseController {

    @Resource
    private MemberBankAccountModel memberBankAccountModel;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @ApiOperation("提现账号列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageSize", value = "分页大小", defaultValue = "20", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面位置", defaultValue = "1", paramType = "query")
    })
    @GetMapping("list")
    public JsonResult<PageVO<MemberBankAccountVO>> getList(HttpServletRequest request) {
        AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_is_enable")), "提现未开启");
        //微信开关
        String wxpayIsEnable = stringRedisTemplate.opsForValue().get("withdraw_wxpay_is_enable");
        //支付宝开关
        String alipayIsEnable = stringRedisTemplate.opsForValue().get("withdraw_alipay_is_enable");

        Member member = UserUtil.getUser(request, Member.class);

        PagerInfo pager = WebUtil.handlerPagerInfo(request);
        MemberBankAccountExample example = new MemberBankAccountExample();
        example.setMemberId(member.getMemberId());
        if ("1".equals(wxpayIsEnable) && "0".equals(alipayIsEnable)) {
            //只开启微信
            example.setAccountCode(MemberWithdrawConst.ACCOUNT_CODE_WXPAY);
        } else if ("0".equals(wxpayIsEnable) && "1".equals(alipayIsEnable)) {
            //只开启支付宝
            example.setAccountCode(MemberWithdrawConst.ACCOUNT_CODE_ALIPAY);
        } else if ("0".equals(wxpayIsEnable) && "0".equals(alipayIsEnable)) {
            //都未开启
            return SldResponse.fail("提现未开启");
        }
        List<MemberBankAccount> list = memberBankAccountModel.getMemberBankAccountList(example, pager);
        List<MemberBankAccountVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(memberBankAccount -> {
                vos.add(new MemberBankAccountVO(memberBankAccount));
            });
        }
        return SldResponse.success(new PageVO<>(vos, pager));
    }

    @ApiOperation("添加账号")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "accountCode", value = "账号编码：ALIPAY-支付宝,WXPAY-微信", required = true),
            @ApiImplicitParam(name = "accountName", value = "账号名称：ALIPAY-支付宝真实姓名"),
            @ApiImplicitParam(name = "accountNumber", value = "账号：ALIPAY-支付宝账号,WXPAY-微信用户授权code(用于获取openid)", required = true),
            @ApiImplicitParam(name = "codeSource", value = "用户code来源（JSAPI支付时必填）：1==小程序，2==微信内部浏览器，3==app")
    })
    @PostMapping("add")
    public JsonResult<Object> addAccount(HttpServletRequest request, @RequestParam(name = "accountCode") String accountCode,
                                 @RequestParam(name = "accountName", required = false) String accountName,
                                 @RequestParam(name = "accountNumber") String accountNumber,
                                 @RequestParam(value = "codeSource", required = false) Integer codeSource) {
        AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_is_enable")), "提现未开启");
        //校验提现方式是否开启
        if ("WXPAY".equals(accountCode)) {
            AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_wxpay_is_enable")), "微信提现未开启");
        } else if ("ALIPAY".equals(accountCode)) {
            AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_alipay_is_enable")), "支付宝提现未开启");
        } else {
            return SldResponse.fail("账号编码有误");
        }

        Member member = UserUtil.getUser(request, Member.class);

        String openId = null;
        //微信类型：APP-app；JSAPI-公众号；MINIAPP-小程序
        String wxType = null;
        //账号不可重复
        MemberBankAccountExample example = new MemberBankAccountExample();
        example.setMemberId(member.getMemberId());
        example.setAccountName(accountName);
        if (accountCode.equals(MemberWithdrawConst.ACCOUNT_CODE_WXPAY)) {
            AssertUtil.notEmpty(accountNumber, "微信用户授权code不能为空");
            AssertUtil.notNullOrZero(codeSource, "用户来源不能为空");
            //app直接取前端传过来的openid
            if (codeSource == 3) {
                openId = accountNumber;
                wxType = PayConst.WX_TYPE_APP;
            } else {
                //如果是微信时根据code获取openid
                openId = this.getOpenId(accountNumber, codeSource);
                if (codeSource == 1) {
                    wxType = PayConst.WX_TYPE_MINIAPP;
                } else {
                    wxType = PayConst.WX_TYPE_JSAPI;
                }
            }
            example.setAccountNumber(openId);
        } else {
            example.setAccountNumber(accountNumber);
        }
        Integer count = memberBankAccountModel.getMemberBankAccountListCount(example);
        AssertUtil.isTrue(count > 0, "账号不可重复");

        MemberBankAccount memberBankAccount = new MemberBankAccount();
        memberBankAccount.setMemberId(member.getMemberId());
        memberBankAccount.setMemberName(member.getMemberName());
        memberBankAccount.setAccountCode(accountCode);
        memberBankAccount.setAccountName(accountName);
        if (accountCode.equals(MemberWithdrawConst.ACCOUNT_CODE_WXPAY)) {
            //如果是微信时传openid
            memberBankAccount.setAccountNumber(openId);
            memberBankAccount.setBankName("微信");
            memberBankAccount.setWxType(wxType);
        } else {
            memberBankAccount.setAccountNumber(accountNumber);
            memberBankAccount.setBankName("支付宝");
        }
        memberBankAccount.setCreateTime(new Date());
        Integer accountId = memberBankAccountModel.saveMemberBankAccount(memberBankAccount);
        return SldResponse.success("新增成功", accountId);
    }

    @ApiOperation("编辑账号(仅限支付宝)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "accountId", value = "账号id", required = true),
            @ApiImplicitParam(name = "accountName", value = "账号名称：支付宝真实姓名", required = true),
            @ApiImplicitParam(name = "accountNumber", value = "账号：支付宝账号", required = true)
    })
    @PostMapping("update")
    public JsonResult<Object> updateAccount(HttpServletRequest request, @RequestParam(name = "accountId") Integer accountId,
                                    @RequestParam(name = "accountName") String accountName,
                                    @RequestParam(name = "accountNumber") String accountNumber) {
        AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_is_enable")), "提现未开启");
        //校验提现方式是否开启
        AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_alipay_is_enable")), "支付宝提现未开启");

        Member member = UserUtil.getUser(request, Member.class);

        MemberBankAccount bankAccount = memberBankAccountModel.getMemberBankAccountByAccountId(accountId);
        AssertUtil.notNull(bankAccount, "账号不存在");
        AssertUtil.isTrue(!bankAccount.getAccountCode().equals(MemberWithdrawConst.ACCOUNT_CODE_ALIPAY), "仅限支付宝可以编辑");

        //账号不可重复
        MemberBankAccountExample example = new MemberBankAccountExample();
        example.setMemberId(member.getMemberId());
        example.setAccountNumber(accountNumber);
        example.setAccountIdNotEquals(accountId);
        Integer count = memberBankAccountModel.getMemberBankAccountListCount(example);
        AssertUtil.isTrue(count > 0, "账号不可重复");

        MemberBankAccount memberBankAccount = new MemberBankAccount();
        memberBankAccount.setAccountId(accountId);
        memberBankAccount.setAccountName(accountName);
        memberBankAccount.setAccountNumber(accountNumber);
        memberBankAccount.setUpdateTime(new Date());
        memberBankAccountModel.updateMemberBankAccount(memberBankAccount);
        return SldResponse.success("编辑成功");
    }

    @ApiOperation("删除账号")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "accountId", value = "账号id", required = true)
    })
    @PostMapping("delete")
    public JsonResult<Object> deleteAccount(HttpServletRequest request, @RequestParam(name = "accountId") Integer accountId) {
        AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_is_enable")), "提现未开启");

        Member member = UserUtil.getUser(request, Member.class);

        MemberBankAccount bankAccount = memberBankAccountModel.getMemberBankAccountByAccountId(accountId);
        AssertUtil.notNull(bankAccount, "账号不存在");
        AssertUtil.isTrue(!bankAccount.getMemberId().equals(member.getMemberId()), "非法操作");
        //校验提现方式是否开启
        if ("WXPAY".equals(bankAccount.getAccountCode())) {
            AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_wxpay_is_enable")), "微信提现未开启");
        } else if ("ALIPAY".equals(bankAccount.getAccountCode())) {
            AssertUtil.isTrue(!"1".equals(stringRedisTemplate.opsForValue().get("withdraw_alipay_is_enable")), "支付宝提现未开启");
        } else {
            return SldResponse.fail("账号有误");
        }

        memberBankAccountModel.deleteMemberBankAccount(accountId);
        return SldResponse.success("删除成功");
    }

    /**
     * 获取微信openId
     *
     * @param code 微信用户授权code
     * @return 微信openId
     */
    @SneakyThrows
    public String getOpenId(String code, Integer codeSource) {
        //获取openid的url
        String tokenUrl;
        if (codeSource == 1) {
            //小程序
            tokenUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + stringRedisTemplate.opsForValue().get("login_wx_mini_appid") +
                    "&secret=" + stringRedisTemplate.opsForValue().get("login_wx_mini_appsecret") + "&js_code=" + code + "&grant_type=authorization_code";
        } else {
            //微信内部浏览器
            tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + stringRedisTemplate.opsForValue().get("login_wx_dev_appid") +
                    "&secret=" + stringRedisTemplate.opsForValue().get("login_wx_dev_appsecret") + "&code=" + code + "&grant_type=authorization_code";
        }
        String resp = HttpUtil.get(tokenUrl);
        if (0 == JSONObject.parseObject(resp).getIntValue("errcode")) {
            return JSONObject.parseObject(resp).getString("openid");
        } else {
            log.error("获取openid出错：" + resp);
            throw new MallException("获取openid出错：");
        }
    }
}
