package com.gci.boot.modules.customer.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.*;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gci.boot.common.util.DateUtils;
import com.gci.boot.constant.CommonConstant;
import com.gci.boot.exception.GciBootException;
import com.gci.boot.modules.basedata.entity.TbCustomerFollowTemplatePart;
import com.gci.boot.modules.basedata.entity.TbInspectionTemplateProject;
import com.gci.boot.modules.basedata.entity.TbVehicle;
import com.gci.boot.modules.basedata.service.ITbCustomerFollowTemplatePartService;
import com.gci.boot.modules.basedata.service.ITbInspectionTemplateProjectService;
import com.gci.boot.modules.basedata.service.ITbInspectionTemplateService;
import com.gci.boot.modules.basedata.service.ITbVehicleService;
import com.gci.boot.modules.customer.entity.*;
import com.gci.boot.modules.customer.mapper.TbScheduledPlanMapper;
import com.gci.boot.modules.customer.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gci.boot.modules.projects.entity.Projects;
import com.gci.boot.modules.projects.service.IProjectsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 定时任务记录表 服务实现类
 * </p>
 *
 * @author 2464
 * @since 2023-10-18
 */
@Service
@Slf4j
public class TbScheduledPlanServiceImpl extends ServiceImpl<TbScheduledPlanMapper, TbScheduledPlan> implements ITbScheduledPlanService {

    @Autowired
    private IProjectsService projectsService;
    @Autowired
    private ITbInspectionTaskService inspectionTaskService;
    @Autowired
    private ITbInspectionTaskProjectService inspectionTaskProjectService;
    @Autowired
    private ITbCustomerFollowService customerFollowService;
    @Autowired
    private ITbInspectionTemplateProjectService inspectionTemplateProjectService;
    @Autowired
    private ITbInspectionTaskPartService inspectionTaskPartService;
    @Autowired
    private ITbCustomerFollowTemplatePartService customerFollowTemplatePartService;
    @Autowired
    private ITbCustomerFollowPartService customerFollowPartService;
    @Autowired
    private ITbVehicleService vehicleService;
    @Autowired
    private ITbInspectionTaskVehicleService inspectionTaskVehicleService;


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addInspection(List<TbScheduledPlan> list) {
        LambdaQueryWrapper<TbScheduledPlan> wrapper = new LambdaQueryWrapper<TbScheduledPlan>().eq(TbScheduledPlan::getPlanType, "2");
        if (ObjectUtil.isEmpty(list)) {
            //传过来空list就全部删除
            remove(wrapper);
            return;
        }
        long count = list.stream().map(TbScheduledPlan::getProjectId).distinct().count();
        if (count < list.size()) {
            throw new GciBootException("项目不能重复！");
        }
        List<TbScheduledPlan> planList = list(wrapper);
        List<String> collect = null;
        if (ObjectUtil.isNotEmpty(planList)) {
            collect = planList.stream().map(TbScheduledPlan::getId).collect(Collectors.toList());
        }
        ArrayList<TbScheduledPlan> needAdd = new ArrayList<>();
        ArrayList<TbScheduledPlan> needEdit = new ArrayList<>();
        for (TbScheduledPlan i : list) {
            i.setPlanType("2");
            checkProject(i.getProjectId());
            if (StrUtil.isBlank(i.getId())) {
                needAdd.add(i);
            } else {
                if (ObjectUtil.isNotEmpty(collect)) {
                    if (collect.contains(i.getId())) {
                        needEdit.add(i);
                        collect.remove(i.getId());
                    }
                }
            }
        }
        if (ObjectUtil.isNotEmpty(needAdd)) {
            saveBatch(needAdd);
        }
        if (ObjectUtil.isNotEmpty(needEdit)) {
            updateBatchById(needEdit);
        }
        if (ObjectUtil.isNotEmpty(collect)) {
            removeByIds(collect);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addCustomer(List<TbScheduledPlan> list) {
        LambdaQueryWrapper<TbScheduledPlan> wrapper = new LambdaQueryWrapper<TbScheduledPlan>().eq(TbScheduledPlan::getPlanType, "1");
        if (ObjectUtil.isEmpty(list)) {
            //传过来空list就全部删除
            remove(wrapper);
            return;
        }
        long count = list.stream().map(TbScheduledPlan::getProjectId).distinct().count();
        if (count < list.size()) {
            throw new GciBootException("项目不能重复！");
        }
        List<TbScheduledPlan> planList = list(wrapper);
        List<String> collect = null;
        if (ObjectUtil.isNotEmpty(planList)) {
            collect = planList.stream().map(TbScheduledPlan::getId).collect(Collectors.toList());
        }
        ArrayList<TbScheduledPlan> needAdd = new ArrayList<>();
        ArrayList<TbScheduledPlan> needEdit = new ArrayList<>();
        for (TbScheduledPlan i : list) {
            i.setPlanType("1");
            if (i.getProjectId().contains(StrUtil.COMMA)) {
                throw new GciBootException("错误项目Id");
            }
            checkProject(i.getProjectId());
            if (StrUtil.isBlank(i.getId())) {
                needAdd.add(i);
            } else {
                if (ObjectUtil.isNotEmpty(collect)) {
                    if (collect.contains(i.getId())) {
                        needEdit.add(i);
                        collect.remove(i.getId());
                    }
                }
            }
        }
        if (ObjectUtil.isNotEmpty(needAdd)) {
            saveBatch(needAdd);
        }
        if (ObjectUtil.isNotEmpty(needEdit)) {
            updateBatchById(needEdit);
        }
        if (ObjectUtil.isNotEmpty(collect)) {
            removeByIds(collect);
        }
    }

    @Override
    public void initPlan() {
        DateTime dateTime = new DateTime();
        gen(dateTime);
    }

    private void gen(DateTime dateTime) {
        List<TbScheduledPlan> list = list();
        if (ObjectUtil.isNotEmpty(list)) {
            Map<String, List<TbScheduledPlan>> collect = list.stream().collect(Collectors.groupingBy(TbScheduledPlan::getPlanType));
            List<TbScheduledPlan> customerFollowPlan = collect.get("1");
            List<TbScheduledPlan> inspectionTaskPlan = collect.get("2");
            if (ObjectUtil.isNotEmpty(customerFollowPlan)) {
                for (TbScheduledPlan plan : customerFollowPlan) {
                    if ("1".equals(plan.getFrequencyType())) {
                        //每周 月内每周一0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        DateTime lastBeginOfMonth = DateUtil.offset(beginOfMonth, DateField.MONTH, 1);
                        List<Date> dates = new ArrayList<>();
                        long between = DateUtil.between(beginOfMonth, lastBeginOfMonth, DateUnit.DAY);
                        for (long i = 0; i < between; i++) {
                            DateTime offset = DateUtil.offset(beginOfMonth, DateField.DAY_OF_MONTH, Convert.toInt(i));
                            int week = offset.dayOfWeek();
                            if (week == 2) {
                                dates.add(offset.toJdkDate());
                            }
                        }
                        buildCustomerFollow(plan, dates);
                    } else if ("2".equals(plan.getFrequencyType())) {
                        //每月 每月1号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        List<Date> dates = new ArrayList<>();
                        dates.add(beginOfMonth);
                        buildCustomerFollow(plan, dates);
                    } else if ("3".equals(plan.getFrequencyType())) {
                        //每月两次 每月1号16号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        DateTime lastBeginOfMonth = DateUtil.offset(beginOfMonth, DateField.DAY_OF_MONTH, 15);
                        List<Date> dates = new ArrayList<>();
                        dates.add(beginOfMonth);
                        dates.add(lastBeginOfMonth);
                        buildCustomerFollow(plan, dates);
                    } else if ("4".equals(plan.getFrequencyType())) {
                        //每半年 每年1月7月1号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        int i = beginOfMonth.monthStartFromOne();
                        if (i == 1 || i == 7) {
                            List<Date> dates = new ArrayList<>();
                            dates.add(beginOfMonth);
                            buildCustomerFollow(plan, dates);
                        }
                    } else if ("5".equals(plan.getFrequencyType())) {
                        //每年 每年一月1号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        int i = beginOfMonth.monthStartFromOne();
                        if (i == 1) {
                            List<Date> dates = new ArrayList<>();
                            dates.add(beginOfMonth);
                            buildCustomerFollow(plan, dates);
                        }
                    }
                }
            }
            if (ObjectUtil.isNotEmpty(inspectionTaskPlan)) {
                for (TbScheduledPlan plan : inspectionTaskPlan) {
                    if ("1".equals(plan.getFrequencyType())) {
                        //每周 月内每周一0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        DateTime lastBeginOfMonth = DateUtil.offset(beginOfMonth, DateField.MONTH, 1);
                        List<Date> dates = new ArrayList<>();
                        long between = DateUtil.between(beginOfMonth, lastBeginOfMonth, DateUnit.DAY);
                        for (long i = 0; i < between; i++) {
                            DateTime offset = DateUtil.offset(beginOfMonth, DateField.DAY_OF_MONTH, Convert.toInt(i));
                            int week = offset.dayOfWeek();
                            if (week == 2) {
                                dates.add(offset.toJdkDate());
                            }
                        }
                        buildInspectionTask(plan, dates);
                    } else if ("2".equals(plan.getFrequencyType())) {
                        //每月 每月1号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        List<Date> dates = new ArrayList<>();
                        dates.add(beginOfMonth);
                        buildInspectionTask(plan, dates);
                    } else if ("3".equals(plan.getFrequencyType())) {
                        //每月两次 每月1号16号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        DateTime lastBeginOfMonth = DateUtil.offset(beginOfMonth, DateField.DAY_OF_MONTH, 15);
                        List<Date> dates = new ArrayList<>();
                        dates.add(beginOfMonth);
                        dates.add(lastBeginOfMonth);
                        buildInspectionTask(plan, dates);
                    } else if ("4".equals(plan.getFrequencyType())) {
                        //每半年 每年1月7月1号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        int i = beginOfMonth.monthStartFromOne();
                        if (i == 1 || i == 7) {
                            List<Date> dates = new ArrayList<>();
                            dates.add(beginOfMonth);
                            buildInspectionTask(plan, dates);
                        }
                    } else if ("5".equals(plan.getFrequencyType())) {
                        //每年 每年一月1号0点
                        DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime);
                        int i = beginOfMonth.monthStartFromOne();
                        if (i == 1) {
                            List<Date> dates = new ArrayList<>();
                            dates.add(beginOfMonth);
                            buildInspectionTask(plan, dates);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void initPlan(String time) {
        DateTime dateTime = DateUtil.parse(time);
        gen(dateTime);
    }


    private void buildInspectionTask(TbScheduledPlan plan, List<Date> dateList) {
        String templateId = plan.getTemplateId();
        if (StrUtil.isBlank(templateId)) {
            templateId = CommonConstant.DEFAULT_INSPECTION;
        }
        for (Date date : dateList) {
            TbInspectionTask inspectionTask = new TbInspectionTask();
            inspectionTask.setInspectionType("1");
            inspectionTask.setInspectionTime(date);
            inspectionTask.setProjectIds(plan.getProjectId());
            inspectionTask.setInspectionResult("2");
            inspectionTask.setSourceType("2");
            inspectionTask.setInspectionTemplateId(templateId);
            inspectionTaskService.save(inspectionTask);
            List<String> split = StrUtil.split(plan.getProjectId(), StrUtil.COMMA);
            ArrayList<TbInspectionTaskProject> inspectionTaskProjects = new ArrayList<>();
            for (String s : split) {
                TbInspectionTaskProject tbInspectionTaskProject = new TbInspectionTaskProject();
                tbInspectionTaskProject.setProjectId(s);
                tbInspectionTaskProject.setInspectionTaskId(inspectionTask.getId());
                inspectionTaskProjects.add(tbInspectionTaskProject);
            }
            inspectionTaskProjectService.saveBatch(inspectionTaskProjects);
            List<TbInspectionTemplateProject> list = inspectionTemplateProjectService.list(new LambdaQueryWrapper<TbInspectionTemplateProject>().eq(TbInspectionTemplateProject::getTemplateId, templateId));
            ArrayList<TbInspectionTaskPart> inspectionTaskParts = new ArrayList<>();
            for (TbInspectionTemplateProject tbInspectionTemplateProject : list) {
                TbInspectionTaskPart tbInspectionTaskPart = new TbInspectionTaskPart();
                tbInspectionTaskPart.setName(tbInspectionTemplateProject.getName());
                tbInspectionTaskPart.setContent(tbInspectionTemplateProject.getContent());
                tbInspectionTaskPart.setSort(tbInspectionTaskPart.getSort());
                tbInspectionTaskPart.setNormal(CommonConstant.YES);
                tbInspectionTaskPart.setTaskId(inspectionTask.getId());
                inspectionTaskParts.add(tbInspectionTaskPart);
            }
            if (inspectionTaskParts.size() > 0) {
                inspectionTaskPartService.saveBatch(inspectionTaskParts);
            }
            List<TbVehicle> vehicleList = vehicleService.list(new LambdaQueryWrapper<TbVehicle>().eq(TbVehicle::getProjectId, plan.getProjectId()));
            ArrayList<TbInspectionTaskVehicle> inspectionTaskVehicles = new ArrayList<>();
            for (TbVehicle vehicle : vehicleList) {
                TbInspectionTaskVehicle taskVehicle = new TbInspectionTaskVehicle();
                taskVehicle.setVehicleId(vehicle.getId());
                taskVehicle.setInspectionTaskId(inspectionTask.getId());
                taskVehicle.setIsNormal(CommonConstant.YES);
                inspectionTaskVehicles.add(taskVehicle);
            }
            inspectionTaskVehicleService.saveBatch(inspectionTaskVehicles);
        }
    }

    private void buildCustomerFollow(TbScheduledPlan plan, List<Date> dateList) {
        ArrayList<TbCustomerFollow> customerFollowArrayList = new ArrayList<>();
        DateTime date1 = DateUtil.date();
        String templateId = plan.getTemplateId();
        if (StrUtil.isBlank(templateId)) {
            templateId = CommonConstant.DEFAULT_CUSTOMER;
        }
        for (Date date : dateList) {
            TbCustomerFollow customerFollow = new TbCustomerFollow();
            customerFollow.setProjectId(plan.getProjectId());
            customerFollow.setFollowNo("HF"+ DateUtils.formatDate(date1.offset(DateField.MILLISECOND,1), DateUtils.HYPHENS_DATETIME4));
            customerFollow.setReviewType("1");
            customerFollow.setResultStatus("0");
            customerFollow.setReviewTime(date);
            customerFollow.setSourceType("2");
            customerFollow.setTemplateId(templateId);
            customerFollowArrayList.add(customerFollow);
        }
        if (customerFollowArrayList.size() > 0) {
            extracted(customerFollowArrayList, date1);
            customerFollowService.saveBatch(customerFollowArrayList);
            for (TbCustomerFollow customerFollow : customerFollowArrayList) {
                List<TbCustomerFollowTemplatePart> list = customerFollowTemplatePartService.list(new LambdaQueryWrapper<TbCustomerFollowTemplatePart>().eq(TbCustomerFollowTemplatePart::getTemplateId, templateId));
                ArrayList<TbCustomerFollowPart> customerFollowParts = new ArrayList<>();
                for (TbCustomerFollowTemplatePart templatePart : list) {
                    TbCustomerFollowPart customerFollowPart = new TbCustomerFollowPart();
                    customerFollowPart.setCategoryName(templatePart.getCategoryName());
                    customerFollowPart.setFollowName(templatePart.getFollowName());
                    customerFollowPart.setSort(templatePart.getSort());
                    customerFollowPart.setTemplatePartId(templatePart.getId());
                    customerFollowPart.setFollowId(customerFollow.getId());
                    customerFollowPart.setPleasedStatus("1");
                    customerFollowParts.add(customerFollowPart);
                }
                customerFollowPartService.saveBatch(customerFollowParts);
            }
        }
    }

    private void extracted(ArrayList<TbCustomerFollow> customerFollowArrayList, DateTime date1) {
        List<TbCustomerFollow> list = customerFollowService.list(new LambdaQueryWrapper<TbCustomerFollow>().in(TbCustomerFollow::getFollowNo, customerFollowArrayList.stream().map(TbCustomerFollow::getFollowNo).collect(Collectors.toList())));
        if (list.size()>0) {
            for (TbCustomerFollow customerFollow : customerFollowArrayList) {
                customerFollow.setFollowNo("HF"+ DateUtils.formatDate(date1.offset(DateField.MILLISECOND,2), DateUtils.HYPHENS_DATETIME4));
            }
            extracted(customerFollowArrayList,date1);
        }

    }


    /**
     * 校验项目
     * @param projectIds
     */
    private void checkProject(String projectIds) {
        List<String> split = StrUtil.split(projectIds, StrUtil.COMMA);
        List<Projects> list = projectsService.list(new LambdaQueryWrapper<Projects>().in(Projects::getId, split));
        if (list.size() != split.size()) {
            throw new GciBootException("错误项目Id！");
        }
    }
}
