package cn.com.ty.lift.business.maintenance.controller;

import cn.com.ty.lift.business.evaluation.dao.entity.Evaluation;
import cn.com.ty.lift.business.evaluation.service.EvaluationService;
import cn.com.ty.lift.business.maintenance.dao.entity.*;
import cn.com.ty.lift.business.maintenance.dao.entity.model.request.MtPlanRequest;
import cn.com.ty.lift.business.maintenance.dao.entity.model.request.MtRecordRequest;
import cn.com.ty.lift.business.maintenance.dao.entity.model.response.MtOptionTree;
import cn.com.ty.lift.business.maintenance.dao.entity.model.response.MtPlanResponse;
import cn.com.ty.lift.business.maintenance.dao.entity.model.response.MtRecordResponse;
import cn.com.ty.lift.business.maintenance.dao.mapper.MaintenanceRecordMapper;
import cn.com.ty.lift.business.maintenance.service.*;
import cn.com.ty.lift.business.project.dao.entity.ProjectLiftRelevance;
import cn.com.ty.lift.business.project.service.ProjectLiftRelevanceService;
import cn.com.ty.lift.common.model.CountPage;
import cn.com.ty.lift.common.utils.ValuePool;
import cn.com.ty.lift.common.verify.Val;
import cn.com.ty.lift.common.verify.Validate;
import cn.com.ty.lift.common.verify.Validation;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.base.Splitter;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 维保管理-日常保养
 * <p>
 *
 * @author wcz
 * @since 2020/1/17 17:24
 */
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("maintenance/record")
public class MaintenanceRecordController {

    private MaintenancePlanService maintenancePlanService;
    private MaintenanceRecordService maintenanceRecordService;
    private MtRecordCostService mtRecordCostService;
    private MtRecordImgService mtRecordImgService;
    private MaintenanceOptionService maintenanceOptionService;
    private ProjectLiftRelevanceService projectLiftRelevanceService;
    private EvaluationService evaluationService;
    private MaintenanceRecordMapper maintenanceRecordMapper;

    /**
     * 根据条件分页查询维保-日常保养
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("pageRecord")
    @Validation(fields = {"mtCompanyId"})
    public RestResponse pageRecord(@Val @RequestBody MtRecordRequest request) {
        //保养单： 按照执行日期由近及远排序
        LocalDate planBegin = request.getPlanBegin();
        LocalDate planEnd = request.getPlanEnd();
        if (Objects.nonNull(planBegin) && Objects.nonNull(planEnd)) {
            Validate.isTrue(planBegin.isBefore(planEnd), ValuePool.beginTimeToEndTimeIllegal(planBegin, planEnd));
        }
        request.addDesc("work_date");
        IPage<MtRecordResponse> pages = maintenanceRecordService.pageRecordByCondition(request);
        long count = maintenanceRecordService.countRecordByCondition(request);
        return RestResponse.success(CountPage.getCountPage(count, pages));
    }

    /**
     * 根据条件分页查询超期的维保计划
     *
     * @param request MtPlanRequest
     * @return RestResponse
     */
    @PostMapping("pagePlan")
    @Validation(fields = {"mtCompanyId"})
    public RestResponse pagePlan(@Val @RequestBody MtPlanRequest request) {
        //计划超期：按计划保养时间由近及远排序
        LocalDate planBegin = request.getPlanBegin();
        LocalDate planEnd = request.getPlanEnd();
        if (Objects.nonNull(planBegin) && Objects.nonNull(planEnd)) {
            Validate.isTrue(planBegin.isBefore(planEnd), ValuePool.beginTimeToEndTimeIllegal(planBegin, planEnd));
        }
        IPage<MtPlanResponse> pages = maintenancePlanService.pagePlanByCondition(request);
        Validate.notNull(pages, ValuePool.MAINTENANCE_PLAN_NOT_EXIST);
        List<MtPlanResponse> records = pages.getRecords();
        if (!records.isEmpty()) {
            List<ProjectLiftRelevance> relevances = projectLiftRelevanceService.listByMtCompany(request.getMtCompanyId());
            records.forEach(record -> {
                Optional<ProjectLiftRelevance> liftRelevance = relevances
                        .stream().filter(r -> (r.getLiftId().equals(record.getLiftId()) && r.getProjectId().equals(record.getProjectId()))).findFirst();
                //如果存在设置的计划间隔
                if (liftRelevance.isPresent()) {
                    ProjectLiftRelevance relevance = liftRelevance.get();
                    int subtract = ValuePool.MAINTENANCE_INTERVAL - relevance.getPlanInterval();
                    //如果设置的计划间隔 >= 法规间隔，直接判断为法规超期；超期类型，1计划超期，2法规超期
                    if (0 >= subtract) {
                        record.setOverdue(2);
                    } else {
                        log.info("PlanDate: {}", record.getPlanDate());
                        LocalDate deadline = record.getPlanDate().plusDays(subtract);
                        log.info("deadline: {}", deadline);
                        //如果超过法规15天，法规超期LocalDate.now() < deadline
                        LocalDateTime max = LocalDateTime.of(deadline, LocalTime.MAX);
                        log.info("maxtime: {}", max);
                        record.setOverdue(LocalDateTime.now().isBefore(max) ? 1 : 2);
                        log.info("overdue: {}", record.getOverdue());
                    }
                } else {
                    //fixme：如果没有设置计划间隔，暂时判定为计划超期
                    record.setOverdue(1);
                }
            });
        }
        long count = maintenancePlanService.countPlanByCondition(request);
        return RestResponse.success(CountPage.getCountPage(count, pages));
    }

    /**
     * 根据id查找,带关联信息
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("one")
    @Validation(fields = {"id"})
    public RestResponse one(@Val @RequestBody MtRecordRequest request) {
        MtRecordResponse entity = getMtRecordResponse(request);
        return RestResponse.success(entity);
    }

    /**
     * @param request 保养单id
     * @return
     * @description 获取多条保养单
     * @date 2020/5/21 5:14 下午
     */
    @PostMapping("many")
    public RestResponse many(@RequestBody MtRecordRequest request) {
        List<MtRecordResponse> mtRecordResponseList = new ArrayList<>();
        if (StringUtils.isNotBlank(request.getRecordIds())) {
            String[] recordIdArray = request.getRecordIds().split(",");
            for (String recordIdStr : recordIdArray) {
                long recordId = Long.parseLong(recordIdStr);
                request.setId(recordId);
                mtRecordResponseList.add(getMtRecordResponse(request));
            }
        }
        return RestResponse.success(mtRecordResponseList);
    }

    private MtRecordResponse getMtRecordResponse(@RequestBody @Val MtRecordRequest request) {
        MtRecordResponse entity = maintenanceRecordService.infoById(request);
        String repairDuration = maintenanceRecordService.getRepairDuration(entity.getRepairDiff());
        entity.setRepairDuration(repairDuration);
        Validate.notNull(entity, ValuePool.MAINTENANCE_RECORD_NOT_EXIST);
        /**
         * 维保项id:0/1/2, 0:无需保养，1：已保养，2：需要更换
         * 保养项目  用键值对的方式存储，如(1:0,2:1,3:1...)
         */
        String maintenanceOption = entity.getMaintenanceOption();
        if (StrUtil.isNotEmpty(maintenanceOption)) {
            Map<String, String> opts = Splitter.on(ValuePool.COMMA).withKeyValueSeparator(ValuePool.COLON).split(maintenanceOption);
            Map<Long, Integer> optMap = new HashMap<>();
            opts.forEach((key, value) -> {
                optMap.put(Long.parseLong(key.trim()), Integer.parseInt(value.trim()));
            });
            Collection<MaintenanceOption> mtOptions = maintenanceOptionService.listByIds(optMap.keySet());
            mtOptions.forEach(option -> {
                option.setOpt(optMap.get(option.getId()));
            });
            entity.setMtOptions(mtOptions);
        }
        Long id = request.getId();
        //查询费用项
        entity.setMtRecordCosts(mtRecordCostService.listByRecord(id));
        //查询图片
        entity.setMtRecordImgs(mtRecordImgService.listByRecord(id));
        //评价
        entity.setEvaluation(evaluationService.findByRecord(id, ValuePool.EVALUATE_SOURCE_MAINTENANCE));
        return entity;
    }

    /**
     * 查看维保单图片list
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("images")
    @Validation(fields = {"id"})
    public RestResponse images(@Val @RequestBody MtRecordRequest request) {
        List<MtRecordImg> mtRecordImgs = mtRecordImgService.listByRecord(request.getId());
        return RestResponse.success(mtRecordImgs);
    }

    /**
     * 维保项 - 树形
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("treeOptions")
    @Validation(fields = {"mtCompanyId", "type", "liftCategory"})
    public RestResponse treeOptions(@Val @RequestBody MtRecordRequest request) {
        Integer type = request.getType();
        Integer liftCategory = request.getLiftCategory();
        Long mtCompanyId = request.getMtCompanyId();
        List<MaintenanceOption> optionList = maintenanceOptionService.listByTypeAndLiftCategory(type, liftCategory, mtCompanyId);
        Validate.notTrue(IterUtil.isEmpty(optionList), ValuePool.MAINTENANCE_OPTION_NOT_EXIST);
        //按照sort groupby
        Map<Integer, List<MaintenanceOption>> mtOptionMap = optionList.stream().collect(Collectors.groupingBy(MaintenanceOption::getSort));
        List<MtOptionTree> mtOptionTrees = new ArrayList<>();
        mtOptionMap.forEach((sort, options) -> {
            mtOptionTrees.add(new MtOptionTree(sort, options));
        });
        return RestResponse.success(mtOptionTrees);
    }

    /**
     * 维保项list
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("listOptions")
    @Validation(fields = {"mtCompanyId", "type", "liftCategory"})
    public RestResponse listOptions(@Val @RequestBody MtRecordRequest request) {
        Integer type = request.getType();
        Integer liftCategory = request.getLiftCategory();
        Long mtCompanyId = request.getMtCompanyId();
        List<MaintenanceOption> optionList = maintenanceOptionService.listByTypeAndLiftCategory(type, liftCategory, mtCompanyId);
        return RestResponse.success(optionList);
    }

    /**
     * 点击填写保养单，带收费项，新增record
     *
     * @param entity MaintenanceRecord
     * @return RestResponse
     */
    @PostMapping("tofill")
    @Validation(fields = {"mtCompanyId", "mtPlanId", "liftId", "liftType", "type", "workDate", "stopDate", "mtRecordCosts", "sparepart", "partsCost"})
    public RestResponse tofill(@Val @RequestBody MaintenanceRecord entity) {
        MaintenancePlan plan = maintenancePlanService.getById(entity.getMtPlanId());
        Validate.notNull(plan, ValuePool.MAINTENANCE_PLAN_NOT_EXIST);
        entity.setWorkerId(plan.getWorkerId());
        entity.setWorkerId1(entity.getWorkerId());
        entity.setPlanDate(plan.getPlanDate());
        entity.setStatus("-2");
        entity.setIsRegular(0);
        //补录
        entity.setIsRepair(1);
        return maintenanceRecordService.tofill(entity);
    }

    /**
     * app端可对超期计划补录工单及评价，补录后需文员审核；
     *
     * @param entity MaintenanceRecord
     * @return RestResponse
     */
    @PostMapping("add")
    public RestResponse add(@Valid @RequestBody MaintenanceRecord entity) {
        MaintenancePlan plan = maintenancePlanService.getById(entity.getMtPlanId());
        Validate.notNull(plan, ValuePool.MAINTENANCE_PLAN_NOT_EXIST);
        entity.setWorkerId(plan.getWorkerId());
        entity.setWorkerId1(entity.getWorkerId());
        entity.setPlanDate(plan.getPlanDate());
        /**
         * app端添加维保单
         * -3：没有维保记录（可以补录）null -> -3
         * -2：已补录工单，（没有维保项，可以继续填写）
         * -1：待审核（通过app端添加的），通过后台添加的，直接 ->2
         */
        if (StrUtil.isEmpty(entity.getMaintenanceOption())) {
            entity.setStatus("-2");
        } else {
            entity.setStatus("-1");
        }
        entity.setIsRegular(0);
        //补录
        entity.setIsRepair(1);
        entity.setWorkDate(LocalDateTime.now());
        entity.setHasEvaluate(0);
        return maintenanceRecordService.tofill(entity);
    }

    /**
     * 通过：app端提交的保养单点通过后生成正式保养单  status:-1 -> 2
     * 清除超期: 超期的计划修改status ->1,workDate -> now
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("pass")
    @Validation(fields = {"id"})
    public RestResponse pass(@Val @RequestBody MtRecordRequest request) {
        MaintenanceRecord entity = maintenanceRecordService.getById(request.getId());
        Validate.notNull(entity, ValuePool.MAINTENANCE_RECORD_NOT_EXIST);
        Validate.notTrue("-1".equals(entity.getStatus()), ValuePool.MAINTENANCE_RECORD_MUST_AUDITING);
        entity.setStatus("2");
        return maintenanceRecordService.pass(entity);
    }

    /**
     * 退回：app提交的保养单，点退回后，app端重新提交
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("refuse")
    @Validation(fields = {"id"})
    public RestResponse refuse(@Val @RequestBody MtRecordRequest request) {
        MaintenanceRecord entity = maintenanceRecordService.getById(request.getId());
        Validate.notNull(entity, ValuePool.MAINTENANCE_RECORD_NOT_EXIST);
        Validate.notTrue("-1".equals(entity.getStatus()), ValuePool.MAINTENANCE_RECORD_MUST_AUDITING);
        boolean result = maintenanceRecordService.removeById(entity.getId());
        return RestResponse.success(result);
    }

    /**
     * 填写保养单-确认，带维保项和现场图片 ，修改record
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("fill")
    @Validation(fields = {"id", "maintenanceOption", "imgs"})
    public RestResponse fill(@Val @RequestBody MtRecordRequest request) {
        return maintenanceRecordService.fill(request);
    }

    /**
     * 补录工单，带收费项，修改record
     *
     * @param entity MaintenanceRecord
     * @return RestResponse
     */
    @PostMapping("workOrder")
    public RestResponse workOrder(@Valid @RequestBody MaintenanceRecord entity) {
        MaintenancePlan plan = maintenancePlanService.getById(entity.getMtPlanId());
        Validate.notNull(plan, ValuePool.MAINTENANCE_PLAN_NOT_EXIST);
        entity.setWorkerId(plan.getWorkerId());
        entity.setWorkerId1(entity.getWorkerId());
        entity.setPlanDate(plan.getPlanDate());
        entity.setStatus("-2");
        entity.setIsRegular(0);
        //补录
        entity.setIsRepair(1);
        return maintenanceRecordService.tofill(entity);
    }

    /**
     * 删除维保记录中的收费项
     *
     * @param request MtRecordRequest
     * @return RestResponse
     */
    @PostMapping("deleteCost")
    @Validation(fields = {"id", "mtRecordCostId"})
    public RestResponse deleteCost(@Val @RequestBody MtRecordRequest request) {
        MtRecordCost mtRecordCost = mtRecordCostService.getById(request.getMtRecordCostId());
        if (Objects.isNull(mtRecordCost)) {
            return RestResponse.success(true);
        }
        MaintenanceRecord record = maintenanceRecordService.getById(request.getId());
        Validate.notNull(record, ValuePool.MAINTENANCE_RECORD_NOT_EXIST);
        return maintenanceRecordService.deleteCost(record, mtRecordCost);
    }

    /**
     * 维保评价，同时修改维保记录的HasEvaluate -> 1
     */
    @PostMapping("evaluate")
    public RestResponse evaluate(@Valid @RequestBody Evaluation entity) {
        MaintenanceRecord record = maintenanceRecordService.getById(entity.getRecordId());
        Validate.notNull(record, ValuePool.MAINTENANCE_RECORD_NOT_EXIST);
        //状态 -1：待审核，0：待处理，1：已签到，保养中，2：完成保养，待评价，3：完成。
        Validate.isTrue("2".equals(record.getStatus()), ValuePool.MAINTENANCE_RECORD_MUST_COMPLETE);
        //1. 根据维保记录中的评价标识判断
        Validate.notEquals(1, record.getHasEvaluate(), ValuePool.MAINTENANCE_HAD_EVALUATE);
        //2. 查询评价记录判断
        int has = evaluationService.countByRecord(entity.getRecordId(), ValuePool.EVALUATE_SOURCE_MAINTENANCE);
        Validate.notTrue(has > 0, ValuePool.MAINTENANCE_HAD_EVALUATE);
        //来源（1 维保；2 急修）
        entity.setSource(ValuePool.EVALUATE_SOURCE_MAINTENANCE);
        entity.setLiftId(record.getLiftId());
        entity.setPostDate(LocalDateTime.now());

        //维保记录设置已评价
        record.setHasEvaluate(1);
        return maintenanceRecordService.evaluate(record, entity);
    }

    @PostMapping("pageByLift")
    @Validation(fields = {"liftId", "projectId", "mtCompanyId"})
    public RestResponse pageByLift(@Val @RequestBody MtRecordRequest request) {
        IPage<MtRecordResponse> pages = maintenanceRecordService.pageByLift(request);
        return RestResponse.success(pages);
    }

    @PostMapping("export")
    @Validation(fields = {"recordIds"})
    public void export(@Val @RequestBody MtRecordRequest mtRecordRequest, HttpServletResponse response) {
        maintenanceRecordService.export(mtRecordRequest, response);
    }
}
