package com.gree.mall.miniapp.logic.policy;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.miniapp.bean.PayDetail;
import com.gree.mall.miniapp.bean.policy.PolicyDetail;
import com.gree.mall.miniapp.bean.policy.PolicyOrderDetail;
import com.gree.mall.miniapp.bean.policy.WorkerRemind;
import com.gree.mall.miniapp.bean.user.CurrentCompanyWechat;
import com.gree.mall.miniapp.enums.ExamineWorkerStatusEnum;
import com.gree.mall.miniapp.enums.IsEnum;
import com.gree.mall.miniapp.enums.IsYesNoEnum;
import com.gree.mall.miniapp.enums.PolicyOrderStutasEnum;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.logic.common.CommonLogic;
import com.gree.mall.miniapp.logic.common.outside.WechatLogic;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.*;
import com.gree.mall.miniapp.utils.IpUtil;
import com.gree.mall.miniapp.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class WorkerLogic {


    @Autowired
    WebsitUserService websitUserService;

    @Autowired
    CommonLogic commonLogic;

    @Autowired
    WorkerPolicyService workerPolicyService;

    @Autowired
    AdminWebsitService adminWebsitService;

    @Autowired
    PolicyService policyService;

    @Autowired
    PolicyRangeService policyRangeService;

    @Autowired
    PolicyWebsitService policyWebsitService;

    @Autowired
    WechatLogic wechatLogic;

    @Autowired
    PolicyOrderService policyOrderService;

    @Autowired
    UserService userService;

    @Autowired
    AgreementService agreementService;

    @Autowired
    AgreementPolicyService agreementPolicyService;

    @Autowired
    MailboxService mailboxService;



    public List<WorkerRemind> remind() {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        List<WebsitUser> websitUsers = websitUserService.lambdaQuery()
                .eq(WebsitUser::getUserId,currentCompanyWechat.getUserId())
                .notIn(WebsitUser::getExamineStatus,ExamineWorkerStatusEnum.QUIT.getKey())
                .list();

        Mailbox mailbox = mailboxService.getById("1");

        List<WorkerRemind> workerReminds = new ArrayList<>();

        for (WebsitUser websitUser : websitUsers) {

            AdminWebsit adminWebsit = adminWebsitService.getById(websitUser.getWebsitId());
            if (!adminWebsit.getAttr().equals("SELF"))
                continue;
            //保险购买状态，没有购买的意外险
            if (websitUser.getExamineStatus().equals(ExamineWorkerStatusEnum.WAIT_WORKER.getKey()) &&
                    workerPolicyService.lambdaQuery().eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                    .in(WorkerPolicy::getStatus,"DSX","BZZ")
                    .eq(WorkerPolicy::getPolicyType,"AC")
                    .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                    .count() < 1 &&

                    workerPolicyService.lambdaQuery().eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                            .eq(WorkerPolicy::getPolicyType,"AC")
                            .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                            .count() < 1

                    &&
                    policyOrderService.lambdaQuery().eq(PolicyOrder::getIsPay,IsYesNoEnum.YES.getKey())
                    .eq(PolicyOrder::getWebsitUserId,websitUser.getId()).count() < 1
            ) {

                WorkerRemind workerRemind = new WorkerRemind();
                workerRemind.setWebsitId(websitUser.getWebsitId());
                workerRemind.setWebsitName(adminWebsit.getName());
                workerRemind.setRemindIn(1);

                workerReminds.add(workerRemind);
            }

            if (websitUser.getExamineStatus().equals(ExamineWorkerStatusEnum.WAIT.getKey()) &&
                    !(workerPolicyService.lambdaQuery()
                            .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                            .eq(WorkerPolicy::getPolicyType,"AC")
                            .count() > 0)) {

                WorkerRemind workerRemind = new WorkerRemind();
                workerRemind.setWebsitId(websitUser.getWebsitId());
                workerRemind.setWebsitName(adminWebsit.getName());
                workerRemind.setRemindIn(4);

                workerReminds.add(workerRemind);
            }

            // 购买的意外险，按配置后过期
            if (  workerPolicyService.lambdaQuery()
                    .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                    .in(WorkerPolicy::getStatus,"DSX","BZZ")
                    .le(WorkerPolicy::getEndTime, DateUtil.offsetDay(new Date(),mailbox.getOverNum()))
                    .eq(WorkerPolicy::getPolicyType,"AC")
                    .count() > 0

                    &&
                    policyOrderService.lambdaQuery()
                            .eq(PolicyOrder::getWebsitUserId,websitUser.getId())
                            .in(PolicyOrder::getPolicyOrderStatus,"DSX","BZZ")
                            .eq(PolicyOrder::getType,"AC")
                            .eq(PolicyOrder::getIsPay,IsYesNoEnum.YES.getKey())
                            .and(item -> item
                            .isNull(PolicyOrder::getStartTime)
                            .or().ge(PolicyOrder::getEndTime, DateUtil.offsetDay(new Date(),mailbox.getOverNum()))

                            )
                            .eq(PolicyOrder::getWebsitUserId,websitUser.getId())
                            .count() < 1

            ){


                List<WorkerPolicy> list = workerPolicyService.lambdaQuery()
                        .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                        .in(WorkerPolicy::getStatus,"DSX","BZZ")
                        .le(WorkerPolicy::getEndTime, DateUtil.offsetDay(new Date(),mailbox.getOverNum()))
                        .eq(WorkerPolicy::getPolicyType,"AC")
                        .list();

                for (WorkerPolicy workerPolicy : list) {

                    if (websitUserService.lambdaQuery().in(WebsitUser::getExamineStatus, ExamineWorkerStatusEnum.WAIT_WORKER.getKey())
                            .eq(WebsitUser::getId,workerPolicy.getWebsitUserId()).count() > 0) {
                        continue;
                    }

                    WorkerRemind workerRemind = new WorkerRemind();
                    workerRemind.setWebsitId(websitUser.getWebsitId());
                    workerRemind.setWebsitName(adminWebsit.getName());
                    workerRemind.setRemindIn(2);
                    workerRemind.setEndTime(workerPolicy.getEndTime());
                    workerRemind.setDay(mailbox.getOverNum());
                    workerReminds.add(workerRemind);

                    workerPolicy.setExTime(DateUtil.endOfDay(new Date())).updateById();
                }

            }

            // 意外险失效，没有购买的意外险
            if (  workerPolicyService.lambdaQuery()
                    .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                    .in(WorkerPolicy::getStatus,"YSX")
                    .notIn(WorkerPolicy::getStatus,"DSX","BZZ")
                    .eq(WorkerPolicy::getPolicyType,"AC")
                    .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                    .count() > 0

                    &&
                    workerPolicyService.lambdaQuery()
                            .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                            .in(WorkerPolicy::getStatus,"DSX","BZZ")
                            .eq(WorkerPolicy::getPolicyType,"AC")
                            .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                            .count() < 1

                    &&
                    policyOrderService.lambdaQuery()
                            .eq(PolicyOrder::getWebsitUserId,websitUser.getId())
                            .in(PolicyOrder::getPolicyOrderStatus,"DSX","BZZ")
                            .eq(PolicyOrder::getType,"AC")
                            .eq(PolicyOrder::getIsPay,IsYesNoEnum.YES.getKey())
                            .eq(PolicyOrder::getWebsitUserId,websitUser.getId())
                            .count() < 1



            ){

                workerPolicyService.lambdaUpdate()
                        .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                        .in(WorkerPolicy::getStatus,"YSX")
                        .notIn(WorkerPolicy::getStatus,"DSX","BZZ")
                        .eq(WorkerPolicy::getPolicyType,"AC")
                        .eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                        .set(WorkerPolicy::getExTime,DateUtil.endOfDay(new Date())).update();

                WorkerRemind workerRemind = new WorkerRemind();
                workerRemind.setWebsitId(websitUser.getWebsitId());
                workerRemind.setWebsitName(adminWebsit.getName());
                workerRemind.setRemindIn(3);

                workerReminds.add(workerRemind);
            }

        }



        return workerReminds;


    }


    public Page<PolicyOrder> myPolicy(Integer pageNum, Integer pageSize) {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        List<WebsitUser> websitUsers = websitUserService.lambdaQuery().eq(WebsitUser::getUserId, currentCompanyWechat.getUserId()).list();

        List<String> collect = websitUsers.stream().map(WebsitUser::getId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(collect))
            return new Page<>();

        Page<PolicyOrder> page = policyOrderService.lambdaQuery()
                .in(PolicyOrder::getWebsitUserId,collect)
                .eq(PolicyOrder::getType,"AC")
                .eq(PolicyOrder::getIsPay,IsYesNoEnum.YES.getKey())
                .orderByDesc(PolicyOrder::getCreateTime)
                .page(new Page<>(pageNum, pageSize));


        return page;

    }

    public PolicyOrderDetail myDetail(String id) {

        PolicyOrder policyOrder = policyOrderService.getById(id);

        PolicyOrderDetail policyOrderDetail = BeanUtil.toBean(policyOrder, PolicyOrderDetail.class);

        Policy policy = policyService.getById(policyOrderDetail.getPolicyId());


        List<PolicyRange> policyRanges = policyRangeService.lambdaQuery().eq(PolicyRange::getPolicyId, policy.getId()).list();
        policyOrderDetail.setPolicy(policy);
        policyOrderDetail.setPolicyRanges(policyRanges);

        List<AgreementPolicy> agreementPolicies = agreementPolicyService.lambdaQuery().eq(AgreementPolicy::getPolicyId, policy.getId()).list();

        if (!CollectionUtils.isEmpty(agreementPolicies)){
            List<Agreement> agreements = agreementService.lambdaQuery().in(Agreement::getId,
                    agreementPolicies.stream().map(AgreementPolicy::getAgreementId).collect(Collectors.toList())
            ).eq(Agreement::getStatus, "ON").list();

            policyOrderDetail.setAgreements(agreements);
        }
        return policyOrderDetail;
    }

    public Page<Policy> policy(String websitId,Integer pageNum, Integer pageSize) {

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        WebsitUser websitUser = websitUserService.lambdaQuery()
                .eq(WebsitUser::getWebsitId, websitId)
                .eq(WebsitUser::getUserId, currentCompanyWechat.getUserId()).last("limit 1").one();

        List<PolicyWebsit> policyWebsits = policyWebsitService.lambdaQuery().eq(PolicyWebsit::getWebsitId, websitId).list();

        if (CollectionUtils.isEmpty(policyWebsits))
            return new Page<>();

        List<PolicyOrder> policyOrderList = policyOrderService
                .lambdaQuery()
                .eq(PolicyOrder::getType, "AC")
                .isNotNull(PolicyOrder::getPolicyId)
                .eq(PolicyOrder::getIsPay,IsYesNoEnum.YES.getKey())
                .eq(PolicyOrder::getWebsitUserId, websitUser.getId())
                .orderByDesc(PolicyOrder::getEndTime)
                .list();

        List<String> policyIds = policyOrderList.stream().map(PolicyOrder::getPolicyId).collect(Collectors.toList());

        WorkerPolicy workerPolicy = workerPolicyService.lambdaQuery().eq(WorkerPolicy::getWebsitUserId, websitUser.getId())
                .eq(WorkerPolicy::getPolicyType, "AC")
                .orderByDesc(WorkerPolicy::getEndTime)
                .last("limit 1").one();

        Date endTime = null;

        if (!CollectionUtil.isEmpty(policyOrderList)){
            endTime = policyOrderList.get(0).getEndTime();
        }

        if (workerPolicy != null ){
            endTime = workerPolicy.getEndTime();
        }

        if (workerPolicy != null && !CollectionUtil.isEmpty(policyOrderList)){
            if (policyOrderList.get(0).getEndTime().after(workerPolicy.getEndTime()))
                endTime = policyOrderList.get(0).getEndTime();
            else
                endTime = workerPolicy.getEndTime();
        }




        Policy policy = policyService.lambdaQuery()
                .in(Policy::getId, policyWebsits.stream().map(PolicyWebsit::getPolicyId).collect(Collectors.toList()))
                .notIn(CollectionUtil.isNotEmpty(policyIds), Policy::getId, policyIds)
                .gt(endTime != null, Policy::getEndTime,endTime)
                .eq(Policy::getIsBuy, IsYesNoEnum.YES.getKey())
                .le(Policy::getPolicyStartTime, new Date())
                .ge(Policy::getEndTime, new Date())
                .orderByAsc(Policy::getEndTime)
                .last("limit 1").one();

        Page<Policy> objectPage = new Page<>();

        if (policy == null)
            return objectPage;

        List<Policy> policies = new ArrayList<>();
        policies.add(policy);
        objectPage.setPages(1);
        objectPage.setTotal(1);
        objectPage.setCurrent(1);
        objectPage.setRecords(policies);

        return objectPage;
    }

    public PolicyDetail detail(String id) {

        Policy policy = policyService.getById(id);
        PolicyDetail policyDetail = BeanUtil.toBean(policy, PolicyDetail.class);

        List<PolicyRange> policyRanges = policyRangeService.lambdaQuery().eq(PolicyRange::getPolicyId, policyDetail.getId()).list();

        policyDetail.setPolicyRanges(policyRanges);


        List<AgreementPolicy> agreementPolicies = agreementPolicyService.lambdaQuery().eq(AgreementPolicy::getPolicyId, policy.getId()).list();

        if (!CollectionUtils.isEmpty(agreementPolicies)){
            List<Agreement> agreements = agreementService.lambdaQuery().in(Agreement::getId,
                    agreementPolicies.stream().map(AgreementPolicy::getAgreementId).collect(Collectors.toList())
            ).eq(Agreement::getStatus, "ON").list();

            policyDetail.setAgreements(agreements);
        }

        return policyDetail;
    }

    public PolicyOrder order(String policyId, String websitId) {
        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();
        Policy policy = policyService.getById(policyId);

        WebsitUser websiUser = websitUserService.lambdaQuery()
                .eq(WebsitUser::getUserId, currentCompanyWechat.getUserId())
                .eq(WebsitUser::getWebsitId, websitId).one();

        if (websiUser == null)
            throw new RemoteServiceException("没有入驻信息");


        AdminWebsit adminWebsit = adminWebsitService.getById(websitId);

        List<WorkerPolicy> workerPolicies = workerPolicyService.lambdaQuery()
                .eq(WorkerPolicy::getWebsitId, websitId)
                .eq(WorkerPolicy::getWorkerId, currentCompanyWechat.getUser().getWorkerNumber())
                .eq(WorkerPolicy::getPolicyType, "AC")
                .orderByDesc(WorkerPolicy::getEndTime)
                .list();

        //取师傅最后时间的后一天，小于保险时间就取保险时间

        Date startTime = new Date();

        if (!CollectionUtils.isEmpty(workerPolicies)){
            startTime = DateUtil.beginOfDay(DateUtil.offsetDay(workerPolicies.get(0).getEndTime(),1));
        }

        if (startTime.before(policy.getStartTime()))
            startTime = policy.getStartTime();

        PolicyOrder policyOrder = new PolicyOrder();
        policyOrder.setId("PW"+IdWorker.getIdStr());

        policyOrder.setPolicyOrderStatus(PolicyOrderStutasEnum.WAIT.getKey());
        policyOrder.setPolicyName(policy.getPolicyName());
        policyOrder.setPolicyId(policy.getId());
        policyOrder.setPolicyNumber(policy.getPolicyNumber());

        policyOrder.setWebsitUserId(websiUser.getId());
        if (startTime.after(policy.getEndTime()))
            throw new RemoteServiceException("已拥有对应时间得保险");

        int month = DateUtil.month(startTime);
        int month2 = DateUtil.month(policy.getEndTime());
        int year = DateUtil.year(startTime);
        int year2 = DateUtil.year(policy.getEndTime());


        Integer integer =(year2-year)*12+( month2-month+1);
        if (integer > 12 || integer < 1)
            throw new RemoteServiceException("保险配置错误");

        BigDecimal price = this.getPayPrice(integer,policy);

        policyOrder.setPayAmount(policy.getPolicyPrice().multiply(price).setScale(2, BigDecimal.ROUND_HALF_UP));

        policyOrder.setIsSend(IsYesNoEnum.NO.getKey());
        policyOrder.setIsReceipt(IsYesNoEnum.NO.getKey());



        policyOrder.setBelongCompany(adminWebsit.getBelongCompany());
        policyOrder.setBelongCompanyCode(adminWebsit.getBelongCompanyCode());

        policyOrder.setPolicyName(policy.getPolicyName());
        policyOrder.setCompanyWechatId(adminWebsit.getCompanyWechatId());
        policyOrder.setCompanyWechatName(adminWebsit.getCompanyWechatName());
        policyOrder.setPolicyId(policy.getId());

        policyOrder.setWebsitId(adminWebsit.getWebsitId());
        policyOrder.setWebsitName(adminWebsit.getName());
        policyOrder.setWorkerIdcard(currentCompanyWechat.getUser().getIdCard());
        policyOrder.setWorkerMobile(currentCompanyWechat.getUser().getMobile());
        policyOrder.setWorkerName(currentCompanyWechat.getUser().getNickName());
        policyOrder.setWorkerNumber(currentCompanyWechat.getUser().getWorkerNumber());
        policyOrder.setBuyUnit(adminWebsit.getInsureSteadUnit());
        policyOrder.setBuyUnit(adminWebsit.getInsureSteadUnit());
        policyOrder.setType("AC");

        policyOrder.insert();

        return policyOrder;
    }

    private BigDecimal getPayPrice(Integer integer,Policy policy) {
        if (integer.equals(1))
            return policy.getMonth1();
        if (integer.equals(2))
            return policy.getMonth2();
        if (integer.equals(3))
            return policy.getMonth3();
        if (integer.equals(4))
            return policy.getMonth4();
        if (integer.equals(5))
            return policy.getMonth5();
        if (integer.equals(6))
            return policy.getMonth6();
        if (integer.equals(7))
            return policy.getMonth7();
        if (integer.equals(8))
            return policy.getMonth8();
        if (integer.equals(9))
            return policy.getMonth9();
        if (integer.equals(10))
            return policy.getMonth10();
        if (integer.equals(11))
            return policy.getMonth11();
        if (integer.equals(12))
            return policy.getMonth12();

        return null;
    }

    public PayDetail pay(String policyOrderId, HttpServletRequest request) {

        String ip = IpUtil.getIpAddr(request);

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();


        String source = StringUtil.isEmpty(commonLogic.getSource())?"B":commonLogic.getSource();

        String miniOpenId = commonLogic.getMiniOpenId();

        PayDetail payDetail = new PayDetail();

        PolicyOrder policyOrder = policyOrderService.getById(policyOrderId);

        AdminWebsit adminWebsit = adminWebsitService.getById(policyOrder.getWebsitId());

        if (StringUtil.isEmpty(adminWebsit.getPayWorkerCodeId()))
            throw new RemoteServiceException("网点支付配置未配置");

        if (source.equals("B")) {
            payDetail = wechatLogic.paymentWebsitH5(policyOrder.getId(), policyOrder.getPayAmount(), currentCompanyWechat.getUser().getOpenId(),
                    "N", ip, adminWebsit.getPayInsureCodeId());
        } else {
            payDetail = wechatLogic.paymentWebsit(policyOrder.getId(), policyOrder.getPayAmount(),
                    miniOpenId,
                    "N", ip, adminWebsit.getPayInsureCodeId(), true);
        }

        return payDetail;
    }

    public Agreement agreement(String id) {
        Agreement agreement = agreementService.getById(id);

        return agreement;
    }

    public List<AdminWebsit> myWebsit() {
        Mailbox mailbox = mailboxService.getById("1");

        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat();

        List<WebsitUser> websitUsers = websitUserService.lambdaQuery().eq(WebsitUser::getUserId, currentCompanyWechat.getUserId())
                .ne(WebsitUser::getExamineStatus,"WAIT").list();

        List<AdminWebsit> adminWebsits = new ArrayList<>();
        for (WebsitUser websitUser : websitUsers) {

            //保障，生效小于1 或 保障待生效，时间小于过期提醒  且  有订单大于提醒日期得保障待生效 小于1
            if ((workerPolicyService.lambdaQuery().eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                    .eq(WorkerPolicy::getPolicyType,"AC")
                    .in(WorkerPolicy::getStatus,"BZZ","DSX").count() < 1 ||
                    workerPolicyService.lambdaQuery().eq(WorkerPolicy::getWebsitUserId,websitUser.getId())
                            .eq(WorkerPolicy::getPolicyType,"AC")
                            .in(WorkerPolicy::getStatus,"BZZ","DSX")
                            .le(WorkerPolicy::getEndTime,DateUtil.endOfDay(DateUtil.offsetDay(new Date(),mailbox.getOverNum())))
                            .count() > 0)

                    &&
                    policyOrderService.lambdaQuery()
                            .eq(PolicyOrder::getWebsitUserId,websitUser.getId())
                            .in(PolicyOrder::getPolicyOrderStatus,"DSX","BZZ")
                            .eq(PolicyOrder::getType,"AC")
                            .eq(PolicyOrder::getIsPay,IsYesNoEnum.YES.getKey())
                            .and(item -> item
                                    .isNull(PolicyOrder::getStartTime)
                                    .or().ge(PolicyOrder::getEndTime, DateUtil.offsetDay(new Date(),mailbox.getOverNum()))

                            )
                            .eq(PolicyOrder::getWebsitUserId,websitUser.getId())
                            .count() < 1


            ) {
                AdminWebsit adminWebsit = adminWebsitService.getById(websitUser.getWebsitId());

                if (!adminWebsit.getAttr().equals("SELF"))
                    continue;
                adminWebsits.add(adminWebsit);
            }

        }

        return adminWebsits;
    }

    public List<Agreement> agreementList(String policyId) {

        List<AgreementPolicy> agreementPolicies = agreementPolicyService.lambdaQuery().eq(AgreementPolicy::getPolicyId, policyId).list();

        if (!CollectionUtils.isEmpty(agreementPolicies)){
            List<Agreement> agreements = agreementService.lambdaQuery().in(Agreement::getId,
                    agreementPolicies.stream().map(AgreementPolicy::getAgreementId).collect(Collectors.toList())
            ).eq(Agreement::getStatus, "ON").list();

            return agreements;
        }
        return new ArrayList<>();
    }
}
