package com.tykj.dev.device.finalcheck.service.impl;

import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.device.finalcheck.entity.domain.FinalDetail;
import com.tykj.dev.device.finalcheck.entity.domain.FinalReport;
import com.tykj.dev.device.finalcheck.entity.vo.FinalReportSelectVo;
import com.tykj.dev.device.finalcheck.entity.vo.FinalReportVo;
import com.tykj.dev.device.finalcheck.repisotry.FinalDetailDao;
import com.tykj.dev.device.finalcheck.repisotry.FinalReportDao;
import com.tykj.dev.device.finalcheck.service.FinalCheckService;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.device.usereport.service.DeviceUseReportService;
import com.tykj.dev.device.usereport.subject.vo.DeviceStatistics;
import com.tykj.dev.misc.exception.ApiException;
import org.apache.commons.lang3.StringUtils;
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 java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;

import static com.tykj.dev.misc.utils.TimestampUtil.localDateToDate;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;

/**
 * FinalCheckServiceImpl.
 *
 * @author Matrix <xhyrzldf@gmail.com>
 * @since 2020/9/28 at 2:26 下午
 */
@Service
public class FinalCheckServiceImpl implements FinalCheckService {

    @Autowired
    private FinalReportDao reportDao;

    @Autowired
    private FinalDetailDao detailDao;

    @Autowired
    private DeviceLibraryDao deviceDao;

    @Autowired
    private DeviceUseReportService dataService;

    @Autowired
    private UserUtils userService;

    @Override
    public FinalReportVo generateReport(LocalDate startTime, LocalDate endTime) {
        String name = startTime+"～"+endTime + "决算报告";
        String unitName = userService.getCurrentUserUnitName();
        String operatorName = userService.getCurrentName();
        FinalReport report = new FinalReport(name, unitName, startTime, endTime, LocalDateTime.now(), operatorName);
        report = reportDao.save(report);
        // 查询这段时间内该单位下的所有装备 并且计数
        List<DeviceLibrary> devices = deviceDao.findAllByUnitBetweenTime(unitName, localDateToDate(startTime), localDateToDate(endTime));
        // 纵向-查 横向-0 委托-0 合计-合计 代管0 收到 发出 报废0
        Map<String, List<DeviceLibrary>> map = devices.stream()
                .collect(groupingBy(DeviceLibrary::getModel));

        List<FinalDetail> detailList = new ArrayList<>();

        Map<String, DeviceStatistics> storageMap = dataService.getStorageStatistics(localDateToDate(startTime), localDateToDate(endTime))
                .stream()
                .collect(toMap(DeviceStatistics::getModel, Function.identity()));

        Map<String, DeviceStatistics> repairMap = dataService.getRepairStatistics(localDateToDate(startTime), localDateToDate(endTime))
                .stream()
                .collect(toMap(DeviceStatistics::getModel, Function.identity()));

        for (Map.Entry<String, List<DeviceLibrary>> entry : map.entrySet()) {
            String model = entry.getKey();
            List<DeviceLibrary> v = entry.getValue();
            Integer received = storageMap.get(model) == null ? 0 : storageMap.get(model).getNum();
            Integer sending = repairMap.get(model) == null ? 0 : repairMap.get(model).getNum();
            detailList.add(new FinalDetail(model, v.get(0).getType(), v.size(), 0, 0, 0, v.size(),
                    0, received, sending, 0, report.getId()));
        }

        detailList = detailDao.saveAll(detailList);

        return report.toVo(detailList);
    }

    @Override
    public Page<FinalReportVo> findAllWithoutDetail(FinalReportSelectVo finalReportSelectVo) {
        LocalDate startTime = finalReportSelectVo.getStartTime();
        LocalDate endTime = finalReportSelectVo.getEndTime();
        String keyword = finalReportSelectVo.getKeyword();
        boolean timeQuery = Objects.nonNull(startTime) && Objects.nonNull(endTime);
        // 如果没有携带关键字且没有指定时间查询，则直接查询，否则添加时间条件
        if (StringUtils.isEmpty(finalReportSelectVo.getKeyword())) {
            if (timeQuery) {
                Specification<FinalReport> pred = Specifications.<FinalReport>and()
                        .gt("startTime", startTime)
                        .lt("endTime", endTime)
                        .build();

                return reportDao.findAll(pred, finalReportSelectVo.getPageable())
                        .map(report -> report.toVo(Collections.emptyList()));
            } else {
                return reportDao.findAll(finalReportSelectVo.getPageable())
                        .map(report -> report.toVo(Collections.emptyList()));
            }
        } else {
            // 如果携带关键字，则构造条件查询器
            Specification<FinalReport> pred = Specifications.<FinalReport>or()
                    .like("name", "%" + keyword + "%")
                    .like("operator", "%" + keyword + "%")
                    .predicate(timeQuery, Specifications.and()
                            .gt("startTime", startTime)
                            .lt("endTime", endTime)
                            .build()
                    )
                    .build();

            return reportDao.findAll(pred, finalReportSelectVo.getPageable())
                    .map(report -> report.toVo(Collections.emptyList()));
        }

    }

    @Override
    public FinalReportVo findReportById(Integer id) {
        FinalReport report = reportDao.findById(id)
                .orElseThrow(() -> new ApiException("查询的id不存在!"));

        List<FinalDetail> detailList = detailDao.findByReportId(report.getId())
                .orElse(Collections.emptyList());

        return report.toVo(detailList);
    }
}
