package com.izouma.zhirongip.service.resource;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.izouma.zhirongip.converter.StringArrayConverter;
import com.izouma.zhirongip.domain.Setting;
import com.izouma.zhirongip.domain.resource.IntellectualProperty;
import com.izouma.zhirongip.dto.IntellectualPropertyDTO;
import com.izouma.zhirongip.dto.PageQuery;
import com.izouma.zhirongip.exception.BusinessException;
import com.izouma.zhirongip.repo.SettingRepo;
import com.izouma.zhirongip.repo.resource.IntellectualPropertyRepo;
import com.izouma.zhirongip.utils.JpaUtils;
import com.izouma.zhirongip.utils.excel.ExcelUtils;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.transaction.Transactional;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class IntellectualPropertyService {

    private final IntellectualPropertyRepo intellectualPropertyRepo;
    private final SettingRepo              settingRepo;

    public Page<IntellectualProperty> all(PageQuery pageQuery) {
        Map<String, Object> query = pageQuery.getQuery();
        String inventor = null;
        if (ObjectUtil.isNotNull(query.get("inventor"))) {
            inventor = Convert.convert(String.class, query.get("inventor"));
            query.remove("inventor");
        }
        String finalInventor = inventor;

        Map<Long, String> settingMap = settingRepo.findAllByFlagIn(CollUtil.newArrayList(27, 28))
                .stream()
                .collect(Collectors.toMap(Setting::getId, Setting::getName));
        return intellectualPropertyRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> and = JpaUtils.toPredicates(pageQuery, IntellectualProperty.class, root, criteriaQuery, criteriaBuilder);
            if (StrUtil.isNotBlank(finalInventor)) {
                Expression<Integer> function = criteriaBuilder.function("FIND_IN_SET", Integer.class, criteriaBuilder.literal(finalInventor), root
                        .get("inventor"));
                and.add(criteriaBuilder.greaterThan(function, 0));
            }

            return criteriaBuilder.and(and.toArray(new Predicate[0]));
        }), JpaUtils.toPageRequest(pageQuery)).map(property -> {
            property.setLawStatus(settingMap.get(property.getLawStatusId()));
            property.setType(settingMap.get(property.getTypeId()));
            return property;
        });
    }

    public IntellectualProperty get(Long id) {
        IntellectualProperty property = intellectualPropertyRepo.findById(id).orElseThrow(new BusinessException("无记录"));
        if (ObjectUtil.isNotNull(property.getTypeId())){
            settingRepo.findById(property.getTypeId())
                    .ifPresent(setting -> property.setType(setting.getName()));
        }
        if (ObjectUtil.isNotNull(property.getLawStatusId())){
            settingRepo.findById(property.getLawStatusId())
                    .ifPresent(setting -> property.setLawStatus(setting.getName()));
        }

        return property;
    }

    public List<IntellectualPropertyDTO> export(List<IntellectualProperty> properties) {
        Map<Long, String> settingMap = settingRepo.findAllByFlagIn(CollUtil.newArrayList(13, 27, 28))
                .stream()
                .collect(Collectors.toMap(Setting::getId, Setting::getName));
        return properties.stream().map(property -> {
            IntellectualPropertyDTO dto = new IntellectualPropertyDTO(property);
            dto.setIndustryClassName(settingMap.get(property.getIndustryClass()));
            dto.setLawStatus(settingMap.get(property.getLawStatusId()));
            dto.setType(settingMap.get(property.getTypeId()));
            return dto;
        }).collect(Collectors.toList());
    }


    @Transactional(rollbackOn = Exception.class)
    public void upload(InputStream is) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) > -1) {
            baos.write(buffer, 0, len);
        }
        baos.flush();

        InputStream indicatorStream = new ByteArrayInputStream(baos.toByteArray());
        List<IntellectualPropertyDTO> dtos = ExcelUtils.readExcel(indicatorStream, IntellectualPropertyDTO.class, 1, 1);

        List<IntellectualProperty> records = new ArrayList<>();
        List<Setting> settings = settingRepo.findAllByFlagIn(CollUtil.newArrayList(13, 27, 28));
        Map<Integer, Map<String, Long>> mapMap = settings
                .stream()
                .collect(Collectors.groupingBy(Setting::getFlag, Collectors.toMap(Setting::getName, Setting::getId)));

        dtos.forEach(dto -> {
            IntellectualProperty property = new IntellectualProperty(dto);

            StringArrayConverter sc = new StringArrayConverter();

            property.setInventor(sc.convertToEntityAttribute(dto.getInventor()));
            property.setIpc(sc.convertToEntityAttribute(dto.getIpc()));

            property.setLawStatusId(mapMap.get(27).get(dto.getLawStatus()));
            property.setTypeId(mapMap.get(28).get(dto.getType()));
            property.setIndustryClass(mapMap.get(13).get(dto.getIndustryClassName()));

            records.add(property);
        });

        intellectualPropertyRepo.saveAll(records);
    }
}
