package com.jsc.oscm.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jsc.oscm.dao.TargetWebsiteRepository;
import com.jsc.oscm.entity.RulesFilter;
import com.jsc.oscm.entity.RulesParser;
import com.jsc.oscm.entity.TargetWebsite;
import com.jsc.oscm.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class TargetWebsiteService {

    @Resource
    TargetWebsiteRepository targetWebsiteRepository;
    @Resource
    RulesParserService rulesParserService;
    @Resource
    RulesFilterService rulesFilterService;
    @Resource
    TaskService taskService;

    public TargetWebsite saveTarget(TargetWebsite targetWebsite) {
        return targetWebsiteRepository.save(targetWebsite);
    }

    public TargetWebsite save(TargetWebsite targetWebsite) {
        boolean isAdd = targetWebsite.getId() == null;
        TargetWebsite savedWebsite = saveTarget(targetWebsite);
        if (isAdd) {
            // 如果ID为空，说明是新增加的站点，需要创建关联task
            if (!taskService.saveCrawlTaskByWebsite(savedWebsite)) {
                delete(savedWebsite);
                return null;
            }
        }
        return savedWebsite;
    }

    public void delete(TargetWebsite targetWebsite) {
        targetWebsiteRepository.delete(targetWebsite);
        taskService.deleteByWebsiteIds(Collections.singletonList(targetWebsite.getId()));
    }

    public void deleteAll(List<TargetWebsite> targetWebsiteList) {
        targetWebsiteRepository.deleteAll(targetWebsiteList);
        targetWebsiteList.forEach(targetWebsite -> taskService.deleteByWebsiteIds(Collections.singletonList(targetWebsite.getId())));
    }

    public List<TargetWebsite> findAll() {
        return targetWebsiteRepository.findAll();
    }

    public List<TargetWebsite> queryPageable(TargetWebsite targetWebsite, Integer index, Integer size) {
        Example<TargetWebsite> example = Example.of(targetWebsite);
        if (targetWebsite.getSiteName() != null) {
            ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("siteName", ExampleMatcher.GenericPropertyMatchers.contains());
            example = Example.of(targetWebsite, matcher);
        }
        Pageable pageable = PageRequest.of(index, size, Sort.by(Sort.Order.desc("id")));
        return targetWebsiteRepository.findAll(example, pageable).getContent();
    }

    public long queryCount(TargetWebsite targetWebsite) {
        Example<TargetWebsite> example = Example.of(targetWebsite);
        if (targetWebsite.getSiteName() != null) {
            ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("siteName", ExampleMatcher.GenericPropertyMatchers.contains());
            example = Example.of(targetWebsite, matcher);
        }
        return targetWebsiteRepository.count(example);
    }

    public Map<String, Object> queryOne(Integer id) {
        TargetWebsite targetWebsite = targetWebsiteRepository.findById(id).orElse(null);
        if (targetWebsite == null) {
            return null;
        }
        RulesParser rulesParser = rulesParserService.findById(targetWebsite.getParserConfig());
        RulesFilter rulesFilter = rulesFilterService.findById(targetWebsite.getFilterConfig());
        Map<String, Object> targetWebsiteRulesMap = StringUtil.objectToMap(targetWebsite);
        targetWebsiteRulesMap.put("parserConfig", rulesParser);
        targetWebsiteRulesMap.put("filterConfig", rulesFilter);
        return targetWebsiteRulesMap;
    }

    public List<Map<String, Object>> queryAll(TargetWebsite targetWebsite) {
        List<Map<String, Object>> targetWebsiteRulesMapList = new ArrayList<>();
        Example<TargetWebsite> example = Example.of(targetWebsite);
        List<TargetWebsite> targetWebsiteList = targetWebsiteRepository.findAll(example);
        List<RulesFilter> allRulesFilter = rulesFilterService.findAll();
        List<RulesParser> allRulesParser = rulesParserService.findAll();
        for (TargetWebsite tw : targetWebsiteList) {
            RulesFilter relatedFilter = allRulesFilter.stream().filter(f -> f.getId().equals(tw.getFilterConfig())).findFirst().orElse(null);
            RulesParser relatedParser = allRulesParser.stream().filter(f -> f.getId().equals(tw.getParserConfig())).findFirst().orElse(null);
            Map<String, Object> targetWebsiteRulesMap = StringUtil.objectToMap(tw);
            targetWebsiteRulesMap.put("parserConfig", relatedParser);
            targetWebsiteRulesMap.put("filterConfig", relatedFilter);
            targetWebsiteRulesMapList.add(targetWebsiteRulesMap);
        }
        return targetWebsiteRulesMapList;
    }

    public List<TargetWebsite> queryAllInfo(TargetWebsite targetWebsite) {
        return targetWebsiteRepository.findAll(Example.of(targetWebsite));
    }

    public JSONObject getCommonCrawlRules(Integer index, Integer size, TargetWebsite targetWebsite) {
        // 采用模糊匹配
        ExampleMatcher matcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING).withIgnoreCase();
        Example<TargetWebsite> example = Example.of(targetWebsite, matcher);
        List<TargetWebsite> targetWebsiteList = targetWebsiteRepository.findAll(example);
        // 去重后的站点名称
        List<String> siteNameList = targetWebsiteList.stream().sorted(Comparator.comparingInt(TargetWebsite::getId).reversed())
                .map(TargetWebsite::getSiteName).distinct().collect(Collectors.toList());
        JSONArray targetWebSiteArr = new JSONArray();
        siteNameList.stream().skip((long) index * size).limit(size).forEach(siteName -> {
            List<TargetWebsite> targetList = targetWebsiteList.stream()
                    .filter(rule -> StringUtils.equals(rule.getSiteName(), siteName)).collect(Collectors.toList());
            List<String> carrierTypeList = targetList.stream().map(TargetWebsite::getCarrierType).distinct().collect(Collectors.toList());
            List<String> resourceTypeList = targetList.stream().map(TargetWebsite::getResourceType).distinct().collect(Collectors.toList());
            List<Integer> weightList = targetList.stream().map(TargetWebsite::getWeight).distinct().collect(Collectors.toList());
            List<Integer> statusList = targetList.stream().map(TargetWebsite::getStatus).distinct().collect(Collectors.toList());
            JSONObject targetCommonObj = new JSONObject();
            targetCommonObj.put("id", targetList.get(0).getId());
            targetCommonObj.put("siteName", siteName);
            targetCommonObj.put("region", targetList.get(0).getRegion());
            targetCommonObj.put("siteType", targetList.get(0).getSiteType());
            targetCommonObj.put("carrierType", StringUtils.join(carrierTypeList, ","));
            targetCommonObj.put("resourceType", StringUtils.join(resourceTypeList, ","));
            targetCommonObj.put("weight", StringUtils.join(weightList, ","));
            targetCommonObj.put("status", StringUtils.join(statusList, ","));
            String url = targetList.get(0).getStartUrl();
            Pattern pattern = Pattern.compile("https?://[^/]+");
            Matcher match = pattern.matcher(url);
            targetCommonObj.put("startUrl", match.find() ? match.group(0) : url);
            targetCommonObj.put("children", targetList);
            targetWebSiteArr.add(targetCommonObj);
        });
        JSONObject resObj = new JSONObject();
        resObj.put("total", siteNameList.size());
        resObj.put("data", targetWebSiteArr);
        return resObj;
    }

    private final ObjectMapper objectMapper = new ObjectMapper();

    public String exportAllWebsites() throws IOException {
        List<TargetWebsite> websites = targetWebsiteRepository.findAll();
        return objectMapper.writeValueAsString(websites);
    }

    /**
     * 从JSON文件导入目标网站数据
     * @param file 包含网站数据的JSON文件
     * @return 导入的记录数量
     */
    public int importWebsites(MultipartFile file) throws IOException {
        // 读取JSON文件内容
        String content = new String(file.getBytes());

        // 解析JSON为对象列表
        List<TargetWebsite> websites = objectMapper.readValue(
                content,
                new TypeReference<List<TargetWebsite>>() {}
        );

        // 保存到数据库
        targetWebsiteRepository.saveAll(websites);

        return websites.size();
    }

}
