package com.uas.platform.b2b.manage.service.impl;

import com.uas.platform.b2b.manage.dao.InvitationRecordDao;
import com.uas.platform.b2b.manage.dao.InviteDao;
import com.uas.platform.b2b.manage.dao.UserBaseInfoDao;
import com.uas.platform.b2b.manage.model.*;
import com.uas.platform.b2b.manage.service.InviteService;
import com.uas.platform.b2b.manage.service.ProductService;
import com.uas.platform.b2b.manage.support.CollectionUtil;
import com.uas.platform.b2b.manage.support.MyException;
import com.uas.platform.b2b.manage.core.util.StringUtils;
import com.uas.platform.b2b.manage.dao.EnterpriseBaseInfoDao;
import com.uas.platform.b2b.manage.support.MyThread;
import com.uas.platform.b2b.manage.support.MyThreadPoolExecutor;
import com.uas.platform.b2b.manage.model.*;
import com.uas.platform.b2b.manage.support.*;
import com.uas.platform.core.model.PageInfo;
import com.uas.platform.core.model.Status;
import com.uas.platform.core.persistence.criteria.CriterionExpression;
import com.uas.platform.core.persistence.criteria.LogicalExpression;
import com.uas.platform.core.persistence.criteria.PredicateUtils;
import com.uas.platform.core.persistence.criteria.SimpleExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;


/**
 * 邀请注册记录
 *
 * @author hejq
 * @date 2018-07-10 16:32
 */
@Service
public class InviteServiceImpl extends BaseService implements InviteService {

    @Autowired
    private InviteDao inviteDao;

    @Autowired
    private EnterpriseBaseInfoDao enterpriseBaseInfoDao;

    @Autowired
    private UserBaseInfoDao userBaseInfoDao;

    @Autowired
    private InvitationRecordDao recordDao;

    @Autowired
    private ProductService productService;

    /**
     * 通过分页信息获取邀请注册记录
     *
     * @param info 分页信息
     * @param keyword 关键词
     * @param fromDate 开始日期
     * @param endDate 截止日期
     * @return
     * @throws ParseException
     */
    @Override
    public Page<Invite> findInviteByPageInfo(final PageInfo info, String keyword, String fromDate, String endDate) throws ParseException {
        if (!StringUtils.isEmpty(keyword)) {
            SimpleExpression name = new SimpleExpression("enName", keyword, CriterionExpression.Operator.LIKE, true);
            SimpleExpression enBussinessCode = new SimpleExpression("enBussinessCode", keyword, CriterionExpression.Operator.LIKE, true);
            SimpleExpression inviteEnName = new SimpleExpression("inviteEnName", keyword, CriterionExpression.Operator.LIKE, true);
            SimpleExpression inviteUserName = new SimpleExpression("inviteUserName", keyword, CriterionExpression.Operator.LIKE, true);
            SimpleExpression adminUserName = new SimpleExpression("adminName", keyword, CriterionExpression.Operator.LIKE, true);
            List<SimpleExpression> expressionList = new ArrayList<>();
            expressionList.add(name);
            expressionList.add(enBussinessCode);
            expressionList.add(inviteEnName);
            expressionList.add(inviteUserName);
            expressionList.add(adminUserName);
            if (keyword.matches(UU_REGEXP)) {
                SimpleExpression enUU = new SimpleExpression("uu", keyword, CriterionExpression.Operator.EQ, true);
                expressionList.add(enUU);
            }
            SimpleExpression[] expressions = expressionList.toArray(new SimpleExpression[expressionList.size()]);
            LogicalExpression logical = new LogicalExpression(expressions, CriterionExpression.Operator.OR);
            info.expression(logical);
        }
        if (!StringUtils.isEmpty(fromDate)) {
            info.expression(PredicateUtils.gte("enDate", SIMPLE_DATE_FORMAT.parse(fromDate), false));
        }
        if (!StringUtils.isEmpty(endDate)) {
            info.expression(PredicateUtils.lte("enDate", SIMPLE_DATE_FORMAT.parse(endDate), false));
        }
        Page<Invite> invites = inviteDao.findAll(new Specification<Invite>() {
            @Override
            public Predicate toPredicate(Root<Invite> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                query.where(info.getPredicates(root, query, builder));
                return null;
            }
        }, info);
        Map<Long, InviteProdInfo> map = productService.findByEnUUList(CollectionUtil.getKeyCollection(invites.getContent()));
        for (Invite invite : invites) {
            if (null != invite.getUu()) {
                InviteProdInfo prodInfo = map.get(invite.getUu());
                if (null != prodInfo) {
                    invite.setProductCount(prodInfo.getCount());
                    invite.setLastProductDate(prodInfo.getLastDate());
                }
            }
        }
        return invites;
    }

    /**
     * 通过企业UU，填写的邀请用户信息，企业信息更新邀请记录
     *
     * @param enUU 被邀请企业UU
     * @param userName 邀请用户姓名
     * @param userTel 邀请用户电话
     * @param userUU 邀请用户UU
     * @param enterName 邀请企业名
     * @param enterUU 邀请企业UU
     * @return
     * @throws MyException
     */
    @Override
    public ModelMap editInvite(final Long enUU, String userName, String userTel, Long userUU, String enterName, Long enterUU) throws MyException {
        boolean userInfo = true;
        if (StringUtils.isEmpty(userName) && StringUtils.isEmpty(userTel) && null == userUU) {
            userInfo = false;
        }
        boolean enterInfo = true;
        if (StringUtils.isEmpty(enterName) && null == enterUU) {
            enterInfo = false;
        }
        if (!userInfo || !enterInfo) {
            throw new MyException("邀请人或邀请企业信息不能为空");
        }
        // 校验用户信息
        final Long inviteUserUU = invalidUserInfo(userName, userTel, userUU);
        final Long inviteUU = invalidEnterpriseInfo(enterName, enterUU);
        String sql = "update sec$enterprises set en_inviteuu = " + inviteUU +
                ", en_inviteuseruu = " + inviteUserUU + " where en_uu = " + enUU;
        jdbcTemplate.execute(sql);
        MyThreadPoolExecutor.executor.execute(new Runnable() {
            @Override
            public void run() {
                // 更新邀请记录
                updateInvitation(inviteUserUU, enUU, inviteUU);
            }
        });
        return new ModelMap("content", inviteDao.findOne(enUU));
    }

    /**
     * 更新邀请记录
     *
     * @param userUU 邀请用户UU
     * @param enUU 被邀请企业UU
     * @param inviteUU 邀请企业UU
     */
    private void updateInvitation(Long userUU, Long enUU, Long inviteUU) {
        EnterpriseBaseInfo enterpriseBaseInfo = enterpriseBaseInfoDao.findOne(enUU);
        EnterpriseBaseInfo inviteEnterprise = enterpriseBaseInfoDao.findOne(inviteUU);
        UserBaseInfo userBaseInfo = userBaseInfoDao.findOne(userUU);
        UserBaseInfo admin = userBaseInfoDao.findOne(enterpriseBaseInfo.getAdminUU());
        List<InvitationRecord> records = recordDao.findByVendname(enterpriseBaseInfo.getEnName());
        if (CollectionUtils.isEmpty(records)) {
            InvitationRecord record = initRecord(enterpriseBaseInfo, inviteEnterprise, userBaseInfo, admin);
            recordDao.save(record);
        } else {
            for (InvitationRecord record : records) {
                Long id = record.getId();
                record = initRecord(enterpriseBaseInfo, inviteEnterprise, userBaseInfo, admin);
                record.setId(id);
            }
            recordDao.save(records);
        }
    }

    /**
     * 初始化邀请注册信息
     *
     * @param enterpriseBaseInfo 被邀请企业信息
     * @param inviteEnterprise 邀请企业信息
     * @param userBaseInfo 邀请用户信息
     * @param admin 注册企业管理员信息
     * @return
     */
    private InvitationRecord initRecord(EnterpriseBaseInfo enterpriseBaseInfo, EnterpriseBaseInfo inviteEnterprise, UserBaseInfo userBaseInfo, UserBaseInfo admin) {
        InvitationRecord record = new InvitationRecord();
        record.setActive(Constant.YES);
        record.setBussinesscode(inviteEnterprise.getEnBusinessCode());
        record.setSource("Manage");
        record.setDate(new Date(System.currentTimeMillis()));
        record.setStatus(Status.DOWNLOADED.value());
        record.setEnuu(inviteEnterprise.getUu());
        record.setUserTel(userBaseInfo.getTel());
        record.setUseruu(userBaseInfo.getUu());
        record.setVendname(enterpriseBaseInfo.getEnName());
        record.setVenduseremail(admin.getEmail());
        record.setVendusername(admin.getName());
        record.setVendusertel(admin.getTel());
        record.setVenduu(enterpriseBaseInfo.getUu());
        return record;
    }

    /**
     * 校验用户信息
     *
     * @param userName 用户姓名
     * @param userTel 用户电话
     * @param userUU 用户UU
     * @return
     * @throws MyException
     */
    private Long invalidUserInfo(String userName, String userTel, Long userUU) throws MyException {
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        if (null != userUU) {
            userBaseInfo = userBaseInfoDao.findOne(userUU);
        }
        if (null == userBaseInfo) {
            if ((!StringUtils.isEmpty(userName) && !StringUtils.isEmpty(userTel))) {
                List<UserBaseInfo> userList = userBaseInfoDao.findByTel(userTel.trim());
                if (userList.size() == 1) {
                    userBaseInfo = userList.get(0);
                } else if (userList.size() > 1) {
                    userList = userBaseInfoDao.findByNameAndTel(userName.trim(), userTel.trim());
                    if (userList.size() == 1) {
                        userBaseInfo = userList.get(0);
                    } else if (userList.size() > 1) {
                        throw new MyException("通过姓名[" + userName + "],[" + userTel + "]查出多条用户信息，请更新邀请用户信息");
                    } else {
                        throw new MyException("通过姓名[" + userName + "],手机[" + userTel + "]未找到用户信息，请更新邀请用户信息");
                    }
                }
            } else {
                throw new MyException("通过UU[" + userUU+ "]未找到用户信息，请更新邀请用户信息");
            }
        }
        if (null == userBaseInfo) {
            throw new MyException("通过姓名[" + userName + "],手机[" + userTel + "],UU[" + userUU + "]未找到用户信息，请更新邀请用户信息");
        }
        return userBaseInfo.getUu();
    }

    /**
     * 校验企业信息
     *
     * @param enterName 邀请企业名称
     * @param enterUU  邀请企业UU
     * @return
     */
    private Long invalidEnterpriseInfo(String enterName, Long enterUU) throws MyException {
        EnterpriseBaseInfo baseInfo = new EnterpriseBaseInfo();
        if (null != enterUU) {
            baseInfo = enterpriseBaseInfoDao.findOne(enterUU);
            if (null == baseInfo.getUu()) {
                throw new MyException(NOT_FOUND_CODE, "通过UU[" + enterUU + "]未找到相关企业信息");
            }
        }
        if (null == baseInfo && !StringUtils.isEmpty(enterName)) {
            List<EnterpriseBaseInfo> baseInfoList = enterpriseBaseInfoDao.findByEnName(enterName.trim());
            if (baseInfoList.size() > 1) {
                throw new MyException("通过名称[" + enterName + "]查出多条企业信息，请更新邀请企业信息");
            } else if (baseInfoList.size() == 1) {
                baseInfo = baseInfoList.get(0);
            } else {
                throw new MyException("通过名称[" + enterName + "]未找到相关企业信息，请更新邀请企业信息");
            }
        }
        if (null == baseInfo) {
            throw new MyException("通过名称[" + enterName + "],UU[" + enterUU + "]未找到相关企业信息，请更新邀请企业信息");
        }
        return baseInfo.getUu();
    }

    /**
     * 清除邀请记录
     *
     * @param enUU 企业UU
     */
    @Override
    public void deleteByUU(Long enUU) {
        String sql = "update sec$enterprises set en_inviteuu = null, en_inviteuseruu = null where en_uu = " + enUU;
        jdbcTemplate.execute(sql);
    }

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                60,
                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
                new MyThread(),
                new ThreadPoolExecutor.AbortPolicy());
        executor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("Tread start");
            }
        });
    }


}
