package cn.newfeifan.mall.sale.service.merchantapply;

import cn.hutool.core.lang.Assert;
import cn.newfeifan.mall.framework.ip.core.Area;
import cn.newfeifan.mall.framework.ip.core.utils.AreaUtils;
import cn.newfeifan.mall.module.enums.MerchantApplyCheckPersonStatusEnum;
import cn.newfeifan.mall.module.enums.MerchantApplyCheckStatusEnum;
import cn.newfeifan.mall.module.enums.MerchantStatusEnum;
import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
import cn.newfeifan.mall.module.member.service.user.MemberUserService;
import cn.newfeifan.mall.module.system.controller.admin.ip.vo.AreaNodeRespVO;
import cn.newfeifan.mall.module.trade.enums.wxmessage.WcChatMessageTemplateIdEnum;
import cn.newfeifan.mall.module.trade.utils.push.JPushUtils;
import cn.newfeifan.mall.module.trade.utils.push.pojo.RequestBody;
import cn.newfeifan.mall.module.trade.utils.wechat.WcChatMessageUtils;
import cn.newfeifan.mall.sale.controller.admin.merchant.vo.MerchantSaveReqVO;
import cn.newfeifan.mall.sale.controller.admin.merchantapply.vo.MerchantApplyPageReqVO;
import cn.newfeifan.mall.sale.controller.admin.merchantapply.vo.MerchantApplySaveReqVO;
import cn.newfeifan.mall.sale.controller.admin.merchantapplylog.vo.MerchantApplyLogSaveReqVO;
import cn.newfeifan.mall.sale.controller.admin.shop.vo.ShopRespVO;
import cn.newfeifan.mall.sale.controller.admin.shop.vo.ShopSaveReqVO;
import cn.newfeifan.mall.sale.dal.dataobject.merchant.MerchantDO;
import cn.newfeifan.mall.sale.service.merchant.MerchantService;
import cn.newfeifan.mall.sale.service.merchantapplylog.MerchantApplyLogService;
import cn.newfeifan.mall.sale.service.shop.ShopService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import cn.newfeifan.mall.sale.dal.dataobject.merchantapply.MerchantApplyDO;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.object.BeanUtils;

import cn.newfeifan.mall.sale.dal.mysql.merchantapply.MerchantApplyMapper;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.newfeifan.mall.module.enums.ErrorCodeConstants.MERCHANT_APPLY_NOT_EXISTS;

/**
 * 商户申请 Service 实现类
 *
 * @author 非繁人
 */
@Service
@Validated
public class MerchantApplyServiceImpl implements MerchantApplyService {

    @Resource
    private MerchantApplyMapper merchantApplyMapper;

    @Resource
    @Lazy
    private MerchantApplyLogService merchantApplyLogService;

    @Resource
    private MerchantService merchantService;

    @Resource
    private ShopService shopService;

    @Resource
    private MemberUserService memberUserService;

    @Resource
    private WcChatMessageUtils wcChatMessageUtils;
    @Resource
    private JPushUtils jPushUtils;

    @Override
    public Long createMerchantApply(MerchantApplySaveReqVO createReqVO) {
        // 插入
        MerchantApplyDO merchantApply = BeanUtils.toBean(createReqVO, MerchantApplyDO.class);
        merchantApply.setCheckStatus(MerchantApplyCheckStatusEnum.AUDIT_PASS.getType());
        merchantApply.setCheckPersonStatus(MerchantApplyCheckPersonStatusEnum.ZERO.getStatus());
        merchantApply.setApplyMemberUserId(getLoginUserId());
        merchantApplyMapper.insert(merchantApply);

        MerchantSaveReqVO bean = BeanUtils.toBean(createReqVO, MerchantSaveReqVO.class);

        bean.setMerchantApplyId(merchantApply.getId());
        merchantService.createMerchant(bean, null);
        // 返回
        return merchantApply.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMerchantApply(MerchantApplySaveReqVO updateReqVO) {
        // 校验存在
        validateMerchantApplyExists(updateReqVO.getId());

        // 登录用户id
        Long loginUserId = getLoginUserId();
        assert loginUserId != null : "登录用户ID不能为空";

        MerchantApplyDO updateDO = BeanUtils.toBean(updateReqVO, MerchantApplyDO.class);
        updateDO.setCheckTime(LocalDateTime.now());
        updateDO.setCheckSystemUserId(loginUserId);

        // 如果审核不通过
        if (updateReqVO.getCheckStatus().equals(MerchantApplyCheckStatusEnum.AUDIT_FAIL.getType())) {
            // 更新
            updateDO.setCheckPersonStatus(MerchantApplyCheckPersonStatusEnum.ERROR.getStatus());
            merchantApplyMapper.updateById(updateDO);

            MerchantApplyLogSaveReqVO build = MerchantApplyLogSaveReqVO.builder()
                    .status(updateDO.getCheckStatus())
                    .merchantApplyId(updateDO.getId())
                    .checkComment(updateDO.getCheckComment())
                    .build();
            merchantApplyLogService.createMerchantApplyLog(build);

            // 商户审核不通过向用户发送微信信息
            sentWxChatMessageToTheMemberUser(updateDO);

            // 商户审核不通过向商户发送极光推送
            jPushToTheMemberUser(updateDO);

            return;
        } else {
            // 审核通过
            // 一级审核人
//            if (MerchantApplyCheckPersonStatusEnum.getCheckPersonStatus(loginUserId).equals(MerchantApplyCheckPersonStatusEnum.ONE.getStatus())) {
//                // 修改为向二级审核人审核,状态不变
//                updateDO.setCheckPersonStatus(MerchantApplyCheckPersonStatusEnum.TWO.getStatus());
//                updateDO.setCheckStatus(MerchantApplyCheckStatusEnum.WAIT_AUDIT.getType());
//                merchantApplyMapper.updateById(updateDO);
//
//                MerchantApplyLogSaveReqVO build = MerchantApplyLogSaveReqVO.builder()
//                        .status(MerchantApplyCheckStatusEnum.AUDIT_PASS.getType())
//                        .merchantApplyId(updateDO.getId())
//                        .checkComment(updateDO.getCheckComment())
//                        .checkSystemUserId(loginUserId)
//                        .build();
//                merchantApplyLogService.createMerchantApplyLog(build);
//
//                // todo 商户审核通过向上级发送微信信息
//                sentWxChantMessageToThSystemUser(updateDO,MerchantApplyCheckPersonStatusEnum.TWO.getUserid());
//
//                // 发送极光推送
//                jPushToThSystemUser(updateDO, MerchantApplyCheckPersonStatusEnum.TWO.getUserid());
//                return;
//            } else
                if (MerchantApplyCheckPersonStatusEnum.getCheckPersonStatus(loginUserId).equals(MerchantApplyCheckPersonStatusEnum.TWO.getStatus())) {
                // 修改为向三级审核人审核,状态不变
                updateDO.setCheckPersonStatus(MerchantApplyCheckPersonStatusEnum.THREE.getStatus());
                updateDO.setCheckStatus(MerchantApplyCheckStatusEnum.WAIT_AUDIT.getType());
                merchantApplyMapper.updateById(updateDO);

                MerchantApplyLogSaveReqVO build = MerchantApplyLogSaveReqVO.builder()
                        .status(MerchantApplyCheckStatusEnum.AUDIT_PASS.getType())
                        .merchantApplyId(updateDO.getId())
                        .checkComment(updateDO.getCheckComment())
                        .checkSystemUserId(loginUserId)
                        .build();
                merchantApplyLogService.createMerchantApplyLog(build);

                // todo 商户审核通过向上级发送微信信息
                sentWxChantMessageToThSystemUser(updateDO,MerchantApplyCheckPersonStatusEnum.THREE.getUserid());
                // 发送极光推送
                jPushToThSystemUser(updateDO, MerchantApplyCheckPersonStatusEnum.THREE.getUserid());

                return;
            }
        }

        updateDO.setCheckPersonStatus(MerchantApplyCheckPersonStatusEnum.ZERO.getStatus());
        // 更新
        merchantApplyMapper.updateById(updateDO);

        MerchantApplyLogSaveReqVO build = MerchantApplyLogSaveReqVO.builder()
                .status(updateDO.getCheckStatus())
                .merchantApplyId(updateDO.getId())
                .checkComment(updateDO.getCheckComment())
                .checkSystemUserId(loginUserId)
                .build();
        merchantApplyLogService.createMerchantApplyLog(build);

        MerchantSaveReqVO bean = BeanUtils.toBean(updateReqVO, MerchantSaveReqVO.class);
        MerchantDO merchantDO = merchantService.selectByApplyId(updateDO.getId());
        // 如果审核通过
        if (Objects.equals(updateDO.getCheckStatus(), MerchantApplyCheckStatusEnum.AUDIT_PASS.getType())) {
            bean.setStatus(MerchantStatusEnum.USING.getType());

            // 创建
            if (merchantDO == null) {

                MemberUserDO user = memberUserService.getUser(updateReqVO.getApplyMemberUserId());

                bean.setId(null);
                bean.setMerchantApplyId(updateDO.getId());
                bean.setContactNumber(user.getMobile());
                merchantService.createMerchant(bean, !user.getMobile().equals(updateReqVO.getContactNumber()) ? updateReqVO.getContactNumber() : null);
            } else {
                // 修改
                bean.setId(merchantDO.getId());
                merchantService.updateMerchant(bean);

                // 修改商户下的店铺
                List<ShopRespVO> merchantAllShop = shopService.getMerchantAllShop(merchantDO.getId());
                for (ShopRespVO shopRespVO : merchantAllShop) {
                    shopRespVO.setAccountName(updateReqVO.getAccountName());
                    shopRespVO.setAccountNumber(updateReqVO.getAccountNumber());
                    shopRespVO.setBankName(updateReqVO.getBankName());
                    shopService.updateShop(BeanUtils.toBean(shopRespVO, ShopSaveReqVO.class));
                }
            }

            // 商户审核通过向用户发送微信信息
            sentWxChatMessageToTheMemberUser(updateDO);
            // 商户审核不通过向商户发送极光推送
            jPushToTheMemberUser(updateDO);
        } else if (Objects.equals(updateDO.getCheckStatus(), MerchantApplyCheckStatusEnum.AUDIT_FAIL.getType())) {
            if (merchantDO != null) {
                merchantDO.setStatus(MerchantStatusEnum.STOP.getType());
                merchantService.updateMerchant(merchantDO);
            }
        }
    }

    /**
     * 发送微信信息到用户
     * @param merchantApply 入驻申请
     */
    private void sentWxChatMessageToTheMemberUser(MerchantApplyDO merchantApply) {
        List<String> params = new ArrayList<>();

        params.add(merchantApply.getName());
        params.add(merchantApply.getCheckStatus().equals(MerchantApplyCheckStatusEnum.AUDIT_PASS.getType()) ? "通过" : "拒绝");

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        params.add(LocalDateTime.now().format(formatter));

        wcChatMessageUtils.sendWcChatMessage(merchantApply.getApplyMemberUserId(), WcChatMessageTemplateIdEnum.MERCHANT_APPLY_CHECK_RESULT.getTemplateId(),
                params, getLoginUserId(), merchantApply.getApplyMemberUserId(), merchantApply.getId());
    }

    private void jPushToTheMemberUser(MerchantApplyDO merchantApply){
        String title = WcChatMessageTemplateIdEnum.MERCHANT_APPLY_CHECK_RESULT.getName();

        String alert = "商户名称: " + merchantApply.getName();
        alert += "\n审核结果: " + (merchantApply.getCheckStatus().equals(MerchantApplyCheckStatusEnum.AUDIT_PASS.getType()) ? "通过" : "拒绝");

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        alert += "\n审核时间: " + LocalDateTime.now().format(formatter);

        List<String> userRsgIds = memberUserService.getUserRsgIds(null, merchantApply.getApplyMemberUserId());
        if (userRsgIds != null && !userRsgIds.isEmpty()) {
            String url = jPushUtils.getUrl(title, merchantApply.getId(), null);
            RequestBody requestBody = jPushUtils.getRequestBody(userRsgIds, alert, title, url);
            jPushUtils.jPush(requestBody, merchantApply.getApplyMemberUserId(), null, merchantApply.getId());
        }
    }

    /**
     * 发送微信信息到系统用户
     * @param merchantApply 入驻申请
     * @param sentSystemUserId 系统用户id
     */
    private void sentWxChantMessageToThSystemUser(MerchantApplyDO merchantApply, Long sentSystemUserId){
        List<String> params = new ArrayList<>();

        params.add(merchantApply.getName());
        params.add(merchantApply.getContact());
        params.add(merchantApply.getContactNumber());
        params.add(merchantApply.getAddress() == null || merchantApply.getAddress().isEmpty() ? "-" : merchantApply.getAddress());
        params.add(getAreaById(merchantApply.getAreaId().intValue()));

        wcChatMessageUtils.sendWcChatMessage(WcChatMessageTemplateIdEnum.MERCHANT_APPLY_CHECK.getTemplateId(),
                params, sentSystemUserId, merchantApply.getId());
    }

    /**
     * 发送极光推送到系统用户
     * @param merchantApply 入驻申请
     * @param sentSystemUserId 系统用户id
     */
    private void jPushToThSystemUser(MerchantApplyDO merchantApply, Long sentSystemUserId){
        String title = WcChatMessageTemplateIdEnum.MERCHANT_APPLY_CHECK.getName();

        String alert = "商户名称: " + merchantApply.getName();
        alert += "\n负责人: " + merchantApply.getContact();
        alert += "\n负责人手机号: " + merchantApply.getContactNumber();

        alert += "\n办公地址: " + (merchantApply.getAddress() == null || merchantApply.getAddress().isEmpty() ? "-" : merchantApply.getAddress());
        alert += "\n所在地: " + getAreaById(merchantApply.getAreaId().intValue());

        // 如果没有权限就不用发送了
        Boolean havePermission = jPushUtils.isHavePermission(sentSystemUserId, title);
        if(!havePermission){
            return;
        }
        List<String> userRsgIds = memberUserService.getUserRsgIds(sentSystemUserId, null);
        if (userRsgIds != null && !userRsgIds.isEmpty()) {
            String url = jPushUtils.getUrl(title, merchantApply.getId(), sentSystemUserId);
            RequestBody requestBody = jPushUtils.getRequestBody(userRsgIds, alert, title, url);
            jPushUtils.jPush(requestBody, merchantApply.getApplyMemberUserId(), sentSystemUserId, merchantApply.getId());
        }
    }

    private String getAreaById(Integer id){
        Area area = AreaUtils.getArea(Area.ID_CHINA);
        Assert.notNull(area, "获取不到中国");
        List<AreaNodeRespVO> bean = BeanUtils.toBean(area.getChildren(), AreaNodeRespVO.class);

        for (AreaNodeRespVO areaNode : bean) {
            if (areaNode.getChildren() != null) {
                String result = findInSubList(areaNode.getChildren(), id);
                if (result != null) {
                    return result;
                }
            }
        }
        return "未找到对应的省市区";
    }

    private String findInSubList(List<AreaNodeRespVO> subList, long childId) {
        for (AreaNodeRespVO areaNode : subList) {
            if (areaNode.getId() == childId) {
                return areaNode.getName();
            }
            if (areaNode.getChildren() != null) {
                String result = findInSubList(areaNode.getChildren(), childId);
                if (result != null) {
                    // 假设我们想要返回整个路径，例如 "北京市东城区"
                    return areaNode.getName() + result;
                }
            }
        }
        return null;
    }

    @Override
    public void deleteMerchantApply(Long id) {
        // 校验存在
        validateMerchantApplyExists(id);
        // 删除
        merchantApplyMapper.deleteById(id);
    }

    private void validateMerchantApplyExists(Long id) {
        if (merchantApplyMapper.selectById(id) == null) {
            throw exception(MERCHANT_APPLY_NOT_EXISTS);
        }
    }

    @Override
    public MerchantApplyDO getMerchantApply(Long id) {
        return merchantApplyMapper.selectById(id);
    }

    @Override
    public PageResult<MerchantApplyDO> getMerchantApplyPage(MerchantApplyPageReqVO pageReqVO) {

        Long loginUserId = getLoginUserId();

        if (loginUserId != null && loginUserId != 1L && MerchantApplyCheckPersonStatusEnum.getCheckPersonStatus(loginUserId) != -1) {
            pageReqVO.setCheckPersonStatus(MerchantApplyCheckPersonStatusEnum.getCheckPersonStatus(loginUserId));
        }

        return merchantApplyMapper.selectPage(pageReqVO);
    }

    @Override
    public Integer selectMerchantApplyCount() {

        LambdaQueryWrapper<MerchantApplyDO> wrapper = new LambdaQueryWrapper<MerchantApplyDO>().eq(MerchantApplyDO::getCheckStatus, MerchantApplyCheckStatusEnum.WAIT_AUDIT.getType());

        Long loginUserId = getLoginUserId();
        if (loginUserId != null && loginUserId != 1L) {
            wrapper.eq(MerchantApplyDO::getCheckPersonStatus, MerchantApplyCheckPersonStatusEnum.getCheckPersonStatus(loginUserId));
        }

        return merchantApplyMapper.selectCount(wrapper).intValue();
    }

}