package me.zhengjie.modules.flow.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.flow.domain.Flow;
import me.zhengjie.modules.flow.repository.FlowRepository;
import me.zhengjie.modules.flow.service.FlowService;
import me.zhengjie.modules.flow.service.dto.FlowDto;
import me.zhengjie.modules.flow.service.dto.FlowQueryCriteria;
import me.zhengjie.modules.flow.service.mapstruct.FlowMapper;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageResult;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;

@Service
@RequiredArgsConstructor
public class FlowServiceImpl implements FlowService {

    private final FlowRepository flowRepository;
    private final FlowMapper flowMapper;

    @Override
    public PageResult<FlowDto> queryAll(FlowQueryCriteria criteria, Pageable pageable) {
        Page<Flow> page = flowRepository.findAll(
                (root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder),
                pageable);
        return PageUtil.toPage(page.map(flowMapper::toDto));
    }

    @Override
    public List<FlowDto> queryAll(FlowQueryCriteria criteria) {
        return flowMapper.toDto(flowRepository.findAll(
                (root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public FlowDto findById(Long flowId) {
        Flow flow = flowRepository.findById(flowId).orElseGet(Flow::new);
        ValidationUtil.isNull(flow.getFlowId(), "Flow", "flowId", flowId);
        return flowMapper.toDto(flow);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Flow resources) {
        flowRepository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Flow resources) {
        Flow flow = flowRepository.findById(resources.getFlowId()).orElseGet(Flow::new);
        ValidationUtil.isNull(flow.getFlowId(), "Flow", "id", resources.getFlowId());
        flow.copy(resources);
        flowRepository.save(flow);
    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long flowId : ids) {
            flowRepository.deleteById(flowId);
        }
    }

    @Override
    public void download(List<FlowDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (FlowDto flow : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("流向用户ID", flow.getUserId());
            map.put("流向类型", flow.getFlowType());
            map.put("流向名称", flow.getFlowName());
            map.put("创建人", flow.getCreateBy());
            map.put("创建时间", flow.getCreateTime());
            map.put("更新人", flow.getUpdateBy());
            map.put("更新时间", flow.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}