package com.mooctest.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mooctest.dao2.BugDao;
import com.mooctest.data.BugDTO;
import com.mooctest.data.ReportDTO;
import com.mooctest.model.Bug;
import com.mooctest.service.BugReportService;
import com.mooctest.util.HttpUtil;
import com.mooctest.util.MongoAPIUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.mooctest.util.MongoAPIUtil.EMBEDDED_KEY;
import static java.util.stream.Collectors.toMap;

@Service
public class BugReportServiceImpl implements BugReportService {

    @Autowired
    BugDao bugDao;

    public List<ReportDTO> getReports(long examId, long caseId) {

        HttpHeaders headers = MongoAPIUtil.createAuthHeaderForMongo();
        HttpEntity<String> entity = new HttpEntity<>(headers);

        Map<String, Object> queryParams = new HashMap<>();
        queryParams.put("examId", examId);
        queryParams.put("caseId", caseId);

        String filterStr = MongoAPIUtil.generateFilterStr(queryParams);
        String url = MongoAPIUtil.genFilterUrlWithMaxPage(MongoAPIUtil.REPORT_COLLECTION);

        RestTemplate rt = HttpUtil.getRestTemplate();
        ResponseEntity<JSONObject> dto = rt.exchange(url, HttpMethod.GET, entity, JSONObject.class, filterStr);

        return extractReportDTOs(dto.getBody().getJSONArray(EMBEDDED_KEY));
    }

    private List<ReportDTO> extractReportDTOs(JSONArray jsonArray) {

        if (jsonArray.size() == 0) {
            return null;
        }
        List<ReportDTO> reportDTOs = jsonArray.toJavaList(ReportDTO.class);
        return reportDTOs.stream()
                .filter(reportDTO -> reportDTO.getBugVOS() != null)
                .collect(Collectors.toList());
    }

    public List<BugDTO> mergeAllBugs(List<ReportDTO> reportDTOs) {
        return reportDTOs.stream()
                .map(ReportDTO::getBugVOS)
                .reduce(new ArrayList<>(), (x, y) -> {
                    x.addAll(y);
                    return x;
                });
    }

    public List<BugDTO> getAllBugs(long examId, long caseId) {
        String caseTakeId = caseId + "-" + examId;
        List<Bug> bugs = bugDao.findByCaseTakeId(caseTakeId);
        return wrapList(bugs);
    }

    private List<BugDTO> wrapList(List<Bug> bugs) {

        return bugs.parallelStream()
                .map(bug -> wrap(bug))
                .collect(Collectors.toList());
    }

    private BugDTO wrap(Bug bug) {
        String[] imgUrls = new String[0];
        if (bug.getImgUrls() != null && !bug.getImgUrls().equals("")) {

            imgUrls = bug.getImgUrls().split(",");
        }
        return BugDTO.builder()
                .id(bug.getId())
                .bugCategory(bug.getBugCategory())
                .caseTakeId(bug.getCaseTakeId())
                .createTimeMillis(bug.getCreateTimeMillis())
                .description(bug.getDescription())
                .imgUrls(imgUrls)
                .recurrent(bug.getRecurrent())
                .severity(bug.getSeverity())
                .build();
    }

    public Map<String, BugDTO> getAllBugsMap(long examId, long caseId) {
        List<BugDTO> bugs = getAllBugs(examId, caseId);
        return bugs.stream().collect(toMap(BugDTO::getId, Function.identity()));
    }


    public BugDTO getBugById(String bugId, long examId, long caseId) {
        Bug bug = bugDao.findOne(bugId);
        return wrap(bug);
    }

    public Map<String, List<BugDTO>> getMasterBugMap(Map<String, List<String>> masterBugIdsMap, Map<String, BugDTO> bugsMap) {

        Map<String, List<BugDTO>> masterBugMap = new HashMap<>();
        masterBugIdsMap.forEach((masterId, bugIds) -> {
            List<BugDTO> bugs = bugIds.stream().map(bugId -> bugsMap.get(bugId))
                    .collect(Collectors.toList());

            masterBugMap.put(masterId, bugs);
        });
        return masterBugMap;
    }

}
