package com.iformall.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxMerchantVo;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author gongbiao
 */
@Service
public class WxMerchantServiceImpl implements WxMerchantService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxMerchantMapper wxMerchantMapper;

    @Autowired
    WxShopMapper wxShopMapper;

    @Autowired
    WxMerchantShopMapper wxMerchantShopMapper;

    @Autowired
    WxMerchantBUserMapper wxMerchantBUserMapper;

    @Autowired
    WxAppinfoMapper wxAppinfoMapper;

    @Autowired
    WxRentContractMapper wxRentContractMapper;

    @Autowired
    WxBillRentMapper wxBillRentMapper;

    @Autowired
    WxCouponMapper wxCouponMapper;

    @Autowired
    WxCouponService wxCouponService;

    @Autowired
    WxProfitSharingReceiverService wxProfitSharingReceiverService;

    @Autowired
    WxBillDepositMapper wxBillDepositMapper;

    @Autowired
    WxMerchantCorpMapper wxMerchantCorpMapper;

    @Autowired
    WxMerchantTaxMapper wxMerchantTaxMapper;

    @Autowired
    WxCouponMerchantMapper wxCouponMerchantMapper;

    @Autowired
    WxRentContractService wxRentContractService;

    @Autowired
    WxLevelConfigService wxLevelConfigService;

    @Override
    public PageInfo<WxMerchant> listAsPage(WxMerchant record, Integer pageIndex, Integer pageSize) {


        WxRentContract wxRentContract = new WxRentContract();
        wxRentContract.setTenantId(record.getTenantId());
        List<WxRentContract> list = wxRentContractMapper.findList(wxRentContract);

        PageHelper.startPage(pageIndex, pageSize);
        List<WxMerchant> merchants = wxMerchantMapper.findList(record);
        for (WxMerchant merchant : merchants) {
            List<WxRentContract> collect = list.stream().filter(ms -> ms.getMerchantId() != null && ms.getMerchantId().equals(merchant.getId())
                    && !ms.getStatus().equals(EnumRentContractStatus.WAIT_SIGN.getCode())
                    && !ms.getStatus().equals(EnumRentContractStatus.CONTRACT_TERMINATE.getCode())
                    && !ms.getStatus().equals(EnumRentContractStatus.INTENTION.getCode())).collect(Collectors.toList());
            if (collect != null && collect.size() > 0) {
                merchant.setRentalStartDate(collect.get(0).getRentalStartDate());
                merchant.setRentalEndDate(collect.get(0).getRentalEndDate());
            }
        }

        PageInfo<WxMerchant> pageInfo = new PageInfo<>(merchants);
        return pageInfo;
    }


    @Override
    public PageInfo<WxMerchantVo> listAsPageCVo(WxMerchantVo record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxMerchantMapper.findListCVo(record));
    }

    @Override
    public WxMerchantVo getMerchantInfo(HashMap<String, String> params) {
        return wxMerchantMapper.getMerchantByCode(params);
    }

    @Override
    public List<WxMerchant> etcpList(WxMerchant record) {
        record.setCarVendorType(EnumCarVendor.CAR_ETCP.getCode());
        return wxMerchantMapper.findList(record);
    }

    @Override
    public WxMerchant getById(Long id) {
        WxMerchant wxMerchant = wxMerchantMapper.selectByPrimaryKey(id);
        if(wxMerchant==null){
            return null;
        }
        WxMerchantShop wxMerchantShop = new WxMerchantShop();
        wxMerchantShop.setMerchantId(wxMerchant.getId());
        wxMerchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode());
        List<Map<String, Object>> shops = new ArrayList<>();

        List<WxMerchantShop> wxMerchantShopList = wxMerchantShopMapper.findList(wxMerchantShop);
        for (WxMerchantShop merchantShop : wxMerchantShopList) {
            wxMerchant.setRentalStartDate(merchantShop.getRentalStartDate());
            wxMerchant.setRentalEndDate(merchantShop.getRentalEndDate());
            WxShop record = new WxShop();
            record.setId(merchantShop.getShopId());
            List<Map<String, Object>> shoplist = wxShopMapper.findListMap(record);
            if (shoplist.size() > 0) {
                shops.add(shoplist.get(0));
            }
        }

        wxMerchant.setShoplist(shops);

        WxMerchantBUser wxMerchantBUser = new WxMerchantBUser();
        wxMerchantBUser.setMerchantId(wxMerchant.getId());
        wxMerchantBUser.setStatus(EnumMerchantBUserStatus.VALID.getCode());
        List<WxMerchantBUser> userList = wxMerchantBUserMapper.findList(wxMerchantBUser);
        wxMerchant.setUsers(userList);

        //分账信息
        WxProfitSharingReceiver receiver = wxProfitSharingReceiverService.findReceiver(wxMerchant);
        if (receiver != null) {
            wxMerchant.setAccountId(receiver.getReceiverAccount());
            wxMerchant.setAccountName(receiver.getTrueName());
            wxMerchant.setAccountTypeValue(receiver.getReceiverType());
        }

        WxMerchantCorp wxMerchantCorp = new WxMerchantCorp();
        wxMerchantCorp.setMerchantId(wxMerchant.getId());
        List<WxMerchantCorp> corps = wxMerchantCorpMapper.findList(wxMerchantCorp);
        if(!corps.isEmpty()){
            wxMerchant.setWxMerchantCorp(corps.get(0));
        }else{
            wxMerchant.setWxMerchantCorp(new WxMerchantCorp());
        }

        WxMerchantTax wxMerchantTax = new WxMerchantTax();
        wxMerchantTax.setMerchantId(wxMerchant.getId());
        List<WxMerchantTax> taxes = wxMerchantTaxMapper.findList(wxMerchantTax);
        if(!taxes.isEmpty()){
            wxMerchant.setWxMerchantTax(taxes.get(0));
        }else{
            wxMerchant.setWxMerchantTax(new WxMerchantTax());
        }

        WxLevelConfig wxLevelConfig = new WxLevelConfig();
        wxLevelConfig.setTenantId(wxMerchant.getTenantId());
        wxMerchant.setLevelConfigList(wxLevelConfigService.listByMerchantId(wxMerchant.getId(),wxLevelConfig));

        return wxMerchant;
    }


    @Override
    public void deleteById(Long id) {
        wxMerchantMapper.deleteByPrimaryKey(id);
    }


    private boolean isCouponMerchantValid(Long couponId) {
        Map paramMap = new HashMap<>();
        paramMap.put("productId",couponId);
        List<WxMerchantVo> merchantVoList = wxCouponMerchantMapper.findMerchantNameList(paramMap);
        if (merchantVoList.stream().anyMatch((cm->cm.getMerchantStatus().equals(EnumMerchantStatus.VALID.getCode())))){
            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void disable(Long id) {
        WxMerchant wxMerchant = wxMerchantMapper.selectByPrimaryKey(id);
        if (wxMerchant == null) {
            logger.info("未发现要停用的商户");
            return;
        }

        if(!wxMerchant.getCarVendorType().equals(EnumCarVendor.CAR_NOTFOUND.getCode())){
            logger.info("不能停用停车商户");
            return;
        }

        wxMerchant.setStatus(EnumMerchantStatus.NOT_VALID.getCode());
        wxMerchantMapper.updateByPrimaryKeySelective(wxMerchant);
        //解绑商铺
        WxMerchantShop wxMerchantShopQuery = new WxMerchantShop();
        wxMerchantShopQuery.setTenantId(wxMerchant.getTenantId());
        wxMerchantShopQuery.setMerchantId(wxMerchant.getId());
        wxMerchantShopQuery.setIsDel(EnumDelStatus.NOT_DEL.getCode());
        List<WxMerchantShop> wxMerchantShopList = wxMerchantShopMapper.findList(wxMerchantShopQuery);
        for(WxMerchantShop wxMerchantShop:wxMerchantShopList){
            wxMerchantShop.setIsDel(EnumDelStatus.DEL.getCode());
            wxMerchantShopMapper.updateByPrimaryKeySelective(wxMerchantShop);
            //更新商铺状态
            WxShop wxShop = new WxShop();
            wxShop.setTenantId(wxMerchant.getTenantId());
            wxShop.setId(wxMerchantShop.getShopId());
            wxShop.setStatus(EnumShopStatus.NOT_RENT.getCode());
            wxShopMapper.updateByPrimaryKeySelective(wxShop);
        }
        //解绑用户
        WxMerchantBUser bUser = new WxMerchantBUser();
        bUser.setMerchantId(wxMerchant.getId());
        List<WxMerchantBUser> wxMerchantBUserMapperList = wxMerchantBUserMapper.findList(bUser);
        for (WxMerchantBUser wxMerchantBUser : wxMerchantBUserMapperList) {
            wxMerchantBUser.setStatus(EnumMerchantBUserStatus.INVALID.getCode());
            wxMerchantBUserMapper.updateByPrimaryKeySelective(wxMerchantBUser);
        }
        //作废卡券
        WxCouponMerchant wxCouponMerchant = new WxCouponMerchant();
        wxCouponMerchant.setTenantId(wxMerchant.getTenantId());
        wxCouponMerchant.setMerchantId(wxMerchant.getId());
        wxCouponMerchant.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode());
        List<WxCouponMerchant> wxCouponMerchantList = wxCouponMerchantMapper.findList(wxCouponMerchant);
        List<Long> couponIds = wxCouponMerchantList.stream().map(cm->cm.getProductId()).collect(Collectors.toList());

        couponIds.stream().filter(cid->!isCouponMerchantValid(cid)).forEach(cid->{
            WxCoupon wxCoupon = new WxCoupon();
            wxCoupon.setId(cid);
            wxCoupon.setTenantId(wxMerchant.getTenantId());
            wxCoupon.setStatus(EnumCouponStatus.COUPON_STATUS_TAKE_OFFF.getCode());
            wxCouponService.saveOrUpdate(wxCoupon);
        });
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData addMerchant(WxMerchant wxMerchant, Long userId) {
        try {

            final IdWorker idWorker = IdWorker.get();
            long merchantId = idWorker.nextId();
            //保存商户商铺的关联
            List<Long> shopidlist = wxMerchant.getShopids();
            if(null!=shopidlist && !shopidlist.isEmpty()){
                Long shopid = shopidlist.get(0);
                WxMerchantShop wxMerchantShop = new WxMerchantShop();
                wxMerchantShop.setTenantId(wxMerchant.getTenantId());
                wxMerchantShop.setShopId(shopid);
                wxMerchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode());
                long count = wxMerchantShopMapper.findList(wxMerchantShop).size();
                if(count>0){
                    return new ResultData(ErrorCode.SHOP_IS_RENT);
                }
                //更新商铺状态
                WxShop wxShop = new WxShop();
                wxShop.setTenantId(wxMerchant.getTenantId());
                wxShop.setId(shopid);
                //已出租
                WxShop shop = wxShopMapper.selectByPrimaryKey(shopid);
                if (shop == null) {
                    return new ResultData(ErrorCode.SHOP_IS_NOT_FOUND);
                }
                if (shop.getStatus().equals(EnumShopStatus.RENT.getCode())) {
                    return new ResultData(ErrorCode.SHOP_IS_RENT);
                }
                wxMerchantShop.setId(idWorker.nextId());
                wxMerchantShop.setMerchantId(merchantId);
                wxMerchantShop.setTenantId(wxMerchant.getTenantId());
                Date shopdate = new Date();
                wxMerchantShop.setUpdateDate(shopdate);
                wxMerchantShop.setCreateDate(shopdate);
                wxMerchantShopMapper.insertSelective(wxMerchantShop);
                wxShop.setStatus(EnumShopStatus.RENT.getCode());
                wxShopMapper.updateByPrimaryKeySelective(wxShop);
            }

            wxMerchant.setId(merchantId);
            Date date = new Date();
            wxMerchant.setStatus(EnumMerchantStatus.VALID.getCode());
            wxMerchant.setUpdateDate(date);
            wxMerchant.setCreateDate(date);
            wxMerchantMapper.insertSelective(wxMerchant);

            //关联合同
            if (wxMerchant.getRentContractId() != null) {
                WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(wxMerchant.getRentContractId());
                if (wxRentContract == null) {
                    return new ResultData(ErrorCode.RENT_CONTRACT_IS_NOT_FOUND);
                }
                if (wxRentContract.getStatus().equals(EnumRentContractStatus.CONTRACT_TERMINATE)) {
                    return new ResultData(ErrorCode.RENT_CONTRACT_IS_TERMINATED);
                }
                wxRentContract.setMerchantId(merchantId);
                wxRentContract.setUpdatetime(new Date());
                wxRentContract.setStatus(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode());
                wxRentContractMapper.updateByPrimaryKeySelective(wxRentContract);

                //预览账单改为正式,并写入商户id(租赁合同需要绑定商户才变成已签约)
                WxBillRent billRent = new WxBillRent();
                billRent.setRentContractId(wxMerchant.getRentContractId());
                billRent.setIsPreview(EnumIsPreview.NO.getCode());
                billRent.setMerchantId(merchantId);
                wxBillRentMapper.updatePreviewStatus(billRent);

                //创建账单
                //wxRentContractService.buildRent(wxMerchant, userId,null,EnumIsPreview.NO.getCode());
                //创建押金
                wxRentContractService.buildDeposit(wxMerchant, userId,wxMerchant.getRentContractId());
            }
            return new ResultData(Result.SUCCESS, "商户创建成功", merchantId);
        } catch (Exception e) {
            logger.error("db failed: 商户创建失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }

    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchant(WxMerchant wxMerchant) {

        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }

            //更新商户商铺关联表
            WxMerchantShop wxMerchantShopQuery = new WxMerchantShop();
            wxMerchantShopQuery.setTenantId(wxMerchant.getTenantId());
            wxMerchantShopQuery.setMerchantId(wxMerchant.getId());
            wxMerchantShopQuery.setIsDel(EnumDelStatus.NOT_DEL.getCode());
            List<WxMerchantShop> wxMerchantShopList = wxMerchantShopMapper.findList(wxMerchantShopQuery);
            WxMerchantShop wxMerchantShop = wxMerchantShopList.get(0);
            wxMerchantShop.setUpdateDate(new Date());
            wxMerchantShopMapper.updateByPrimaryKeySelective(wxMerchantShop);

            //更新商户
            Date date = new Date();
            wxMerchant.setUpdateDate(date);
            wxMerchantMapper.updateByPrimaryKeySelective(wxMerchant);
            return new ResultData(Result.SUCCESS, "商户更新成功");
        } catch (Exception e) {
            logger.error("db failed: 商户更新失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }

    }

    @Transactional(isolation=Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantAccount(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            //添加商户的分账账户（不是必选）
            if (wxMerchant.getAccountId() != null
                    && wxMerchant.getAccountName() != null
                    && !wxMerchant.getAccountId().isEmpty()
                    && !wxMerchant.getAccountName().isEmpty()) {
                WxProfitSharingReceiver receiver = new WxProfitSharingReceiver();
                receiver.setReceiverAccount(wxMerchant.getAccountId());
                receiver.setReceiverComments(wxMerchant.getName());
                receiver.setReceiverType(wxMerchant.getAccountTypeValue());
                receiver.setTrueName(wxMerchant.getAccountName());
                receiver.setParameter(wxMerchant.getAccountParameter());
                return wxProfitSharingReceiverService.updateReceiver(wxMerchant, receiver);
            }
        } catch (Exception e) {
            logger.error("db failed: 账户操作失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");

    }


    @Transactional(isolation=Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantCorp(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            WxMerchantCorp wxMerchantCorp = new WxMerchantCorp();
            wxMerchantCorp.setMerchantId(wxMerchant.getId());
            List<WxMerchantCorp> list = wxMerchantCorpMapper.findList(wxMerchantCorp);
            if(list.isEmpty()){
                final IdWorker idWorker = IdWorker.get();
                WxMerchantCorp record = wxMerchant.getWxMerchantCorp();
                record.setId(idWorker.nextId());
                record.setTenantId(wxMerchant.getTenantId());
                record.setMerchantId(wxMerchant.getId());
                Date date = new Date();
                record.setCreateDate(date);
                record.setUpdateDate(date);
                wxMerchantCorpMapper.insertSelective(record);
            }else{
                WxMerchantCorp record = wxMerchant.getWxMerchantCorp();
                Date date = new Date();
                record.setUpdateDate(date);
                wxMerchantCorpMapper.updateByPrimaryKeySelective(record);
            }
        } catch (Exception e) {
            logger.error("db failed: 操作法人信息失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");

    }

    @Transactional(isolation=Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantTax(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            WxMerchantTax wxMerchantTax = new WxMerchantTax();
            wxMerchantTax.setMerchantId(wxMerchant.getId());
            List<WxMerchantTax> list = wxMerchantTaxMapper.findList(wxMerchantTax);
            if(list.isEmpty()){
                final IdWorker idWorker = IdWorker.get();
                WxMerchantTax record = wxMerchant.getWxMerchantTax();
                record.setId(idWorker.nextId());
                record.setTenantId(wxMerchant.getTenantId());
                record.setMerchantId(wxMerchant.getId());
                Date date = new Date();
                record.setCreateDate(date);
                record.setUpdateDate(date);
                wxMerchantTaxMapper.insertSelective(record);
            }else{
                WxMerchantTax record = wxMerchant.getWxMerchantTax();
                Date date = new Date();
                record.setUpdateDate(date);
                wxMerchantTaxMapper.updateByPrimaryKeySelective(record);
            }
        } catch (Exception e) {
            logger.error("db failed: 操作税务信息失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");

    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantAdmin(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            WxAppinfo wxAppinfo = new WxAppinfo();
            wxAppinfo.setTenantId(wxMerchant.getTenantId());
            wxAppinfo.setType(EnumAppType.B.getCode());
            List<WxAppinfo> list = wxAppinfoMapper.findList(wxAppinfo);
            if (list.size() == 0) {
                return new ResultData(ErrorCode.APP_ID_NOT_FOUND);
            }
            wxAppinfo = list.get(0);
            List<WxMerchantBUser> users = wxMerchant.getUsers();

            //删除之前的关联用户
            WxMerchantBUser bUser = new WxMerchantBUser();
            bUser.setMerchantId(wxMerchant.getId() != null ? wxMerchant.getId() : 0);
            List<WxMerchantBUser> wxMerchantBUserMapperList = wxMerchantBUserMapper.findList(bUser);
            for (WxMerchantBUser wxMerchantBUser : wxMerchantBUserMapperList) {
                wxMerchantBUser.setStatus(EnumMerchantBUserStatus.INVALID.getCode());
                wxMerchantBUserMapper.updateByPrimaryKeySelective(wxMerchantBUser);
            }
            final IdWorker idWorker = IdWorker.get();
            //保存商户关联用户
            for (WxMerchantBUser user : users) {
                if (user.getId() == null) {
                    long id = idWorker.nextId();
                    user.setId(id);
                    user.setMerchantId(wxMerchant.getId());
                    user.setTenantId(wxMerchant.getTenantId());
                    user.setAppId(wxAppinfo.getAppId());
                    Date date = new Date();
                    user.setCreateDate(date);
                    user.setUpdateDate(date);
                    user.setStatus(EnumMerchantBUserStatus.VALID.getCode());
                    wxMerchantBUserMapper.insertSelective(user);
                } else {//有id的更新
                    user.setMerchantId(wxMerchant.getId());
                    user.setTenantId(wxMerchant.getTenantId());
                    user.setAppId(wxAppinfo.getAppId());
                    Date date = new Date();
                    user.setUpdateDate(date);
                    user.setStatus(EnumMerchantBUserStatus.VALID.getCode());
                    wxMerchantBUserMapper.updateByPrimaryKeySelective(user);
                }
            }
            return new ResultData(Result.SUCCESS, "账号操作成功");
        } catch (Exception e) {
            logger.error("db failed: 账号操作失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
    }

    @Override
    public ResultData updateMerchantLevel(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            wxMerchantMapper.updateByPrimaryKeySelective(wxMerchant);
            wxLevelConfigService.batchSaveByMerchantId(wxMerchant.getTenantId(), wxMerchant.getId(), wxMerchant.getLevelConfigList());
        } catch (Exception e) {
            logger.error("db failed: 账号操作失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");
    }
}
