package com.jeequan.jeepay.mch.ctrl.member;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.export.MemberInfoExportExcel;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.ExcelUtil;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.MemberAccountHistory;
import com.jeequan.jeepay.db.entity.MemberInfo;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.MemberAccountHistoryService;
import com.jeequan.jeepay.service.impl.MemberInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 会员管理
 *
 * @author xiaoyu
 *
 * @date 2023/4/13 17:22
 */
@RestController
@RequestMapping("/api/member")
public class MemberController extends CommonCtrl {

    @Autowired private MemberInfoService memberInfoService;
    @Autowired private MchInfoService mchInfoService;
    @Autowired private MemberAccountHistoryService accountHistoryService;

    /**
     * @author: xiaoyu
     * @date: 2023/4/13 17:24
     * @describe: 会员列表
     */
    @PreAuthorize("hasAuthority('ENT_MEMBER_LIST')")
    @GetMapping
    public ApiRes list() {
        MemberInfo memberInfo = getObject(MemberInfo.class);
        LambdaQueryWrapper<MemberInfo> wrapper = MemberInfo.gw();
        wrapper.eq(MemberInfo::getMchNo, getCurrentMchNo());

        // 额外条件参数
        JSONObject paramJSON = getReqParamJSON();

        // 会员查询条件
        memberInfoService.memberParams(memberInfo, wrapper);

        wrapper.orderByDesc(MemberInfo::getCreatedAt);

        // 二合一 会员名称/手机号
        if (paramJSON != null && StringUtils.isNotEmpty(paramJSON.getString("unionQueryParam"))) {
            wrapper.and(wr -> {
                wr.like(MemberInfo::getMbrTel, paramJSON.getString("unionQueryParam"))
                        .or().like(MemberInfo::getMbrName, paramJSON.getString("unionQueryParam"));
            });
        }

        IPage<MemberInfo> page = memberInfoService.page(getIPage(), wrapper);
        // 手机号脱敏
        page.getRecords().stream().forEach(i -> i.setMbrTel(DesensitizedUtil.mobilePhone(i.getMbrTel())));

        return ApiRes.page(page);
    }

    /**
     * @author: xiaoyu
     * @date: 2023/4/13 17:36
     * @describe: 新增会员
     */
    @PreAuthorize("hasAuthority('ENT_MEMBER_ADD')")
    @MethodLog(remark = "新增会员")
    @PostMapping
    public ApiRes add() {
        MemberInfo memberInfo = getObject(MemberInfo.class);
        memberInfo.setMbrId("B" + DateUtil.currentSeconds());
        memberInfo.setMchNo(getCurrentMchNo());
        memberInfo.setBalance(0L);
        memberInfo.setSafeKey(JeepayKit.genAccountSafeKey(memberInfo.getMbrId(), 0L));
        memberInfo.setAvatarUrl(getMemberAvatarDefault());

        if (StringUtils.isEmpty(memberInfo.getMbrTel())) {
            throw new BizException("会员手机号不可为空");
        }

        // 查询当前会员是否已存在
        MemberInfo dbMemberInfo = memberInfoService.selectOne(getCurrentMchNo(), null, memberInfo.getMbrTel(), null, null);
        if (dbMemberInfo != null) {
            throw new BizException(memberInfo.getMbrTel() + "当前会员已存在");
        }

        boolean result = memberInfoService.save(memberInfo);
        if (!result) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
        }
        return ApiRes.ok();
    }

    /**
     * @author: xiaoyu
     * @date: 2023/4/13 17:49
     * @describe: 会员信息
     */
    @PreAuthorize("hasAnyAuthority('ENT_MEMBER_VIEW', 'ENT_MEMBER_EDIT')")
    @GetMapping("/{mbrId}")
    public ApiRes detail(@PathVariable("mbrId") String mbrId) {

        MemberInfo memberInfo = memberInfoService.selectOne(getCurrentMchNo(), mbrId, null, null, null);

        if (memberInfo == null || !memberInfo.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }

        return ApiRes.ok(memberInfo);
    }

   /**
    * @author: xiaoyu
    * @date: 2023/4/13 17:51
    * @describe: 更新会员信息
    */
    @PreAuthorize("hasAuthority('ENT_MCH_APP_EDIT')")
    @MethodLog(remark = "更新会员信息")
    @PutMapping("/{mbrId}")
    public ApiRes update(@PathVariable("mbrId") String mbrId) {
        MemberInfo memberInfo = getObject(MemberInfo.class);
        memberInfo.setMbrId(mbrId);
        memberInfo.setMchNo(null);
        memberInfo.setBalance(null);
        memberInfo.setSafeKey(null);
        memberInfo.setMbrTel(null);

        // 校验当前会员信息
        MemberInfo dbMemberInfo = memberInfoService.getById(mbrId);
        if (dbMemberInfo == null) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }

        if (!dbMemberInfo.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
        }

        // 更新信息
        boolean result = memberInfoService.updateById(memberInfo);
        if (!result) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
        }

        return ApiRes.ok();
    }

    /**
     * @author: xiaoyu
     * @date: 2023/4/14 14:30
     * @describe: 会员调账
     */
    @PreAuthorize("hasAuthority('ENT_MEMBER_MANUAL')")
    @MethodLog(remark = "会员调账")
    @PostMapping("/manual/{mbrId}")
    public ApiRes manual(@PathVariable("mbrId") String mbrId) {
        // 变动金额
        Long changeAmount = getRequiredAmountL("changeAmount");
        // 登录密码
        String currentPassword = Base64.decodeStr(getValStringRequired("currentPassword"));

        // 校验当前会员信息
        MemberInfo dbMemberInfo = memberInfoService.getById(mbrId);
        if (dbMemberInfo == null) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }

        // 权限校验
        if (!dbMemberInfo.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
        }

        // 验证商户支付密码
        MchInfo mchInfo = mchInfoService.getById(dbMemberInfo.getMchNo());
        if(!new BCryptPasswordEncoder().matches(currentPassword, mchInfo.getSipw())){
            throw new BizException("支付密码验证失败！");
        }

        // 会员调账
        accountHistoryService.updateMbrAccountAndInsertHistory(dbMemberInfo.getMchNo(), null, null, dbMemberInfo.getMbrId(), changeAmount,
                MemberAccountHistory.BIZ_MANUAL, null, null);

        return ApiRes.ok();
    }

    /**
     * @author: xiaoyu
     * @date: 2023/4/17 17:25
     * @describe: 会员列表数据导出
     */
    @RequestMapping(value="/exportExcel", method = RequestMethod.GET)
    public void exportExcel() {
        try {
            MemberInfo memberInfo = getObject(MemberInfo.class);
            LambdaQueryWrapper<MemberInfo> wrapper = MemberInfo.gw();

            wrapper.eq(MemberInfo::getMchNo, getCurrentMchNo());
            // 会员查询条件
            memberInfoService.memberParams(memberInfo, wrapper);

            wrapper.orderByDesc(MemberInfo::getCreatedAt);

            IPage<MemberInfo> memberList = memberInfoService.page(getIPage(true), wrapper);

            List<JSONObject> newList = new LinkedList<>();
            for (MemberInfo info: memberList.getRecords()) {
                JSONObject object = (JSONObject) JSONObject.toJSON(info);
                object.put("balance", AmountUtil.convertCent2Dollar(info.getBalance()));
                newList.add(object);
            }

            List<MemberInfoExportExcel> linkedList = JSONArray.parseArray(JSONArray.toJSONString(newList), MemberInfoExportExcel.class);
            // excel输出
            ExcelUtil.exportExcel(linkedList, "会员信息", "会员信息", MemberInfoExportExcel.class, "会员信息", response);
        }catch (Exception e) {
            logger.error("导出excel失败", e);
            throw new BizException("导出订单失败！");
        }
    }

    /**
     * @author: xiaoyu
     * @date: 2023/4/18 9:32
     * @describe: 会员统计
     */
    @RequestMapping(value="/count", method = RequestMethod.GET)
    public ApiRes count() {
        MemberInfo memberInfo = getObject(MemberInfo.class);

        // 状态不作为参数传入
        memberInfo.setState(null);
        LambdaQueryWrapper<MemberInfo> wrapper = MemberInfo.gw();
        wrapper.eq(MemberInfo::getMchNo, getCurrentMchNo());
        // 查询参数
        memberInfoService.memberParams(memberInfo, wrapper);
        Map count = memberInfoService.count(wrapper);
        return ApiRes.ok(count);
    }

}
