package com.lantone.qc.trans.comsis;

import com.google.common.collect.Lists;
import com.lantone.qc.pub.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description :
 * @Author : HUJING
 * @Date: 2020/9/10 13:48
 */
@Slf4j
public class CommonAnalysisUtil {

    /**
     * 取文书中全部文本
     *
     * @param html
     * @return
     */
    public static String html2String(String html) {
        try {
            Document document = Jsoup.parse(html);
            Element body = document.select("body").first();
            List<Node> nodes = body.childNodes();
            Node node = nodes.get(0);
            if (" ".equals(node.toString())) {
                node = nodes.get(1);
            }
            String htmlContent = null;
            if (node instanceof Element) {
                Element element = (Element) node;
                htmlContent = element.text();
            }
            return htmlContent;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return "";
        }
    }

    public static void html2StructureMap(List<String> titles, String htmlText, Map<String, String> structureMap) {
        List<String> sortTitles = sortTitles(titles, htmlText);
        cutByTitles(htmlText, sortTitles, 0, structureMap);
    }

    /**
     * 将html内容以行为单位存进list,从<hr>之后开始处理
     *
     * @param html 原始html内容
     * @return
     */
    public List<String> html2List(String html, boolean existHr) {
        List<String> htmlText = Lists.newArrayList();
        Document document = Jsoup.parse(html);
        Element body = document.select("body").first();
        List<Node> nodes = body.childNodes();
        List<Node> subNodes = nodes.get(0).childNodes();
        boolean findNode = false;
        for (Node node : subNodes) {
            if ("hr".equals(node.nodeName())) {
                findNode = true;
                continue;
            }
            if (findNode || !existHr) {
                Element element = (Element) node;
                Elements elements = element.select("div");
                for (Element e : elements) {
                    String text = e.text();
                    if (text.length() > 150) {
                        continue;
                    }
                    htmlText.add(text);
                }
            }
        }
        if (htmlText.get(0).length() > 200) {
            htmlText.remove(0);
        }
        return htmlText;
    }

    /**
     * 将html内容以table的格式存进list
     *
     * @param html 原始html内容
     * @return
     */
    public void html2ListByTable(String html, List<String> htmlText) {
        Elements trs = Jsoup.parse(html).select("table").select("tr");
        for (int i = 0; i < trs.size(); i++) {
            Elements tds = trs.get(i).select("td");
            for (int j = 0; j < tds.size(); j++) {
                String text = tds.get(j).text();
                htmlText.add(text);
            }
        }
    }

    /**
     * 将list中html内容转换成structureMap
     *
     * @param titles       文书各标题
     * @param htmlText     html内容以行的形式存储list
     * @param structureMap
     * @return
     */
    public void html2StructureMap(List<String> titles, List<String> htmlText, Map<String, String> structureMap) {
        StringBuffer sb = new StringBuffer();
        for (String line : htmlText) {
            String text = line.replaceAll("[   ]", " ");
            if (text.length() == 0) {
                continue;
            }
            sb.append(text).append("\n");
        }
        html2StructureMap(titles, sb.toString(), structureMap);
    }

    /**
     * 根据文书各标题截取相应文本，存入structmap中
     *
     * @param line         原始文本
     * @param titles       文书各标题
     * @param depth        递归深度，也就是titles取值时的下标值
     * @param structureMap 存储结构化数据
     */
    public static void cutByTitles(String line, List<String> titles, int depth, Map<String, String> structureMap) {
        if (depth > titles.size() || titles.size() == 0) {
            return;
        }
        String beforeTitle = null, title = null, newTitle = null, value = null;
        beforeTitle = StringUtil.removeBlank(titles.get(Math.max(depth - 1, 0)));
        title = titles.get(Math.min(depth, titles.size() - 1));
        if (depth == titles.size()) {
            /*if (line.contains("\n")) {
                line = line.split("\n")[0];
            }
            */
            value = line.replace("\n", "");
            if (StringUtil.isBlank(structureMap.get(beforeTitle))) {
                structureMap.put(beforeTitle, StringUtil.trim(value));
            }
            return;
        }
        if (line.contains(title + "：") || line.contains(title + ":")) {
            if (line.contains(title + "：")) {
                newTitle = title + "：";
            } else {
                newTitle = title + ":";
            }
            if (depth > 0) {
                value = line.substring(0, line.indexOf(newTitle));
                if (StringUtil.isBlank(structureMap.get(beforeTitle))) {
                    structureMap.put(beforeTitle, StringUtil.trim(value).replace("\n", ""));
                }
            }
            line = line.substring(line.indexOf(newTitle) + newTitle.length());
            depth++;
        } else {
            titles.remove(depth);
        }
        cutByTitles(line, titles, depth, structureMap);
    }

    /**
     * 将title根据在文本中的位置排序
     *
     * @param titles
     * @param content
     * @return
     */
    public static List<String> sortTitles(List<String> titles, String content) {
        Map<Integer, String> titleIndex = new TreeMap<>();
        int index, index_1, index_2;
        for (String title : titles) {
            index_1 = content.indexOf(title + "：");
            index_2 = content.indexOf(title + ":");
            index = Math.max(index_1, index_2);
            if (index != -1) {
                titleIndex.put(index, title);
                StringBuffer sb = new StringBuffer(title.length());
                for (int i = 0; i < title.length(); i++) {
                    sb.append('*');
                }
                content = content.substring(0, index) + sb.toString() + content.substring(index + title.length() + 1);
                //                content = content.substring(0, index) + content.substring(index + title.length() + 1);
            }
        }
        titles = Lists.newArrayList(titleIndex.values());
        return titles;
    }

    /**
     * 标题没有冒号版本
     */
    public static void html2StructureMapNoColon(List<String> titles, String htmlText, Map<String, String> structureMap) {
        List<String> sortTitlesNoColon = sortTitlesNoColon(titles, htmlText);
        cutByTitlesNoColon(htmlText, sortTitlesNoColon, 0, structureMap);
    }

    /**
     * 标题没有冒号版本
     */
    public static void cutByTitlesNoColon(String line, List<String> titles, int depth, Map<String, String> structureMap) {
        if (depth > titles.size() || titles.size() == 0) {
            return;
        }
        String beforeTitle = null, title = null, newTitle = null, value = null;
        beforeTitle = StringUtil.removeBlank(titles.get(Math.max(depth - 1, 0)));
        title = titles.get(Math.min(depth, titles.size() - 1));
        if (depth == titles.size()) {
            value = line;
            value = value.trim();
            if (value.startsWith(":") || value.startsWith("：")) {
                value = value.replaceFirst("[:：]", "");
            }
            if (StringUtil.isBlank(structureMap.get(beforeTitle))) {
                structureMap.put(beforeTitle, StringUtil.trim(value).replace("\n", ""));
            }
            return;
        }
        if (line.contains(title)) {
            newTitle = title;
            if (depth > 0) {
                value = line.substring(0, line.indexOf(newTitle));
                value = value.trim();
                if (value.startsWith(":") || value.startsWith("：")) {
                    value = value.replaceFirst("[:：]", "");
                }
                if (StringUtil.isBlank(structureMap.get(beforeTitle))) {
                    structureMap.put(beforeTitle, StringUtil.trim(value).replace("\n", ""));
                }
            }
            line = line.substring(line.indexOf(newTitle) + newTitle.length());
            depth++;
        } else {
            titles.remove(depth);
        }
        cutByTitlesNoColon(line, titles, depth, structureMap);
    }

    /**
     * 标题没有冒号版本
     */
    public static List<String> sortTitlesNoColon(List<String> titles, String content) {
        Map<Integer, String> titleIndex = new TreeMap<>();
        int index;
        for (String title : titles) {
            index = content.indexOf(title);
            if (index != -1) {
                titleIndex.put(index, title);
                content = content.replace(title, "");
            }
        }
        titles = Lists.newArrayList(titleIndex.values());
        return titles;
    }

    /**
     * 抽取文本中的第一个时间
     *
     * @param top
     * @return
     */
    public static String extractDate(String top) {
        Pattern pattern = Pattern.compile("[0-9]{4}[-][0-9]{1,2}[-][0-9]{1,2}([ ][0-9]{1,2}[:][0-9]{1,2}([:][0-9]{1,2})?)?");
        Matcher matcher = pattern.matcher(top);
        if (matcher.find()) {
            return matcher.group(0);
        } else {
            Pattern p1 = Pattern.compile("[0-9]{4}年[0-9]+月[0-9]+日[0-9]+时[0-9]+分");
            Matcher m1 = p1.matcher(top);
            if (m1.find()) {
                return m1.group(0);
            } else {
                Pattern p2 = Pattern.compile("[0-9]{4}年[0-9]+月[0-9]+日 [0-9]+:[0-9]+ | [0-9]{4}年[0-9]+月[0-9]+日[0-9]+:[0-9]+ ");
                Matcher m2 = p2.matcher(top);
                if (m2.find()) {
                    return m2.group(0);
                }
            }
        }
        return null;
    }

    /**
     * 宁海医院抽取文本中的第一个时间
     *
     * @param top
     * @return
     */
    public static String NHExtractDate(String top) {
        Pattern pattern = Pattern.compile("[0-9]{4}年[0-9]+月[0-9]+日 [0-9]+:[0-9]+ | [0-9]{4}年[0-9]+月[0-9]+日[0-9]+:[0-9]+");
        Matcher matcher = pattern.matcher(top);
        if (matcher.find()) {
            return matcher.group(0);
        } else {
            Pattern p1 = Pattern.compile("[0-9]{4}年[0-9]+月[0-9]+日[0-9]+时[0-9]+分");
            Matcher m1 = p1.matcher(top);
            if (m1.find()) {
                return m1.group(0);
            } else {
                Pattern p2 = Pattern.compile("[0-9]{4}[-][0-9]{1,2}[-][0-9]{1,2}([ ][0-9]{1,2}[:][0-9]{1,2}([:][0-9]{1,2})?)?");
                Matcher m2 = p2.matcher(top);
                if (m2.find()) {
                    return m2.group(0);
                }
            }
        }
        return null;
    }

    /**
     * 根据title重新存放时间
     *
     * @param structmap
     * @param title
     */
    public static void extractDateByTitle(Map<String, String> structmap, String title) {
        if (structmap.containsKey(title)) {
            String date = extractDate(structmap.get(title));
            if (StringUtil.isNotBlank(date)) {
                structmap.put(title, date);
            }
        }
    }

    /**
     * 若内容中是包含选择框（会诊类型：     急会诊       普通会诊         请院外会诊），特殊处理
     *
     * @param structureMap
     */
    public static void processType(Map<String, String> structureMap, String title) {
        if (structureMap.containsKey(title)) {
            String type = structureMap.get(title);
            String[] types = type.split(" ");
            for (String t : types) {
                if (t.contains("\uF0FE")) {
                    structureMap.put(title, t.replace("\uF0FE", ""));
                    break;
                }
            }
        }
    }

    /**
     * 若list中其中一个元素包含之后第二个、第三个元素的文本，则把这个元素删除
     *
     * @param htmlList
     */
    public static void removeRepeat(List<String> htmlList) {
        List<Integer> index = Lists.newArrayList();
        if (htmlList.size() < 3) {
            return;
        }
        String str1 = null, str2 = null, str3 = null;
        for (int i = 0; i < htmlList.size() - 2; i++) {
            str1 = htmlList.get(i);
            str2 = htmlList.get(i + 1);
            str3 = htmlList.get(i + 2);
            if (str1.contains(str2) && str1.contains(str3)) {
                index.add(i);
            }
        }

        for (int i = 0; i < index.size(); i++) {
            htmlList.remove(index.get(i) - i);
        }
    }

    /**
     * 宁海用抽取自定义病程录信息
     *
     * @param htmlText
     * @param structureMap
     */
    public static void NHExtractWardInfo(String recTitle, String htmlText, Map<String, String> structureMap) {
        if (StringUtil.isNotBlank(htmlText)) {
            htmlText = htmlText.replaceAll("[   \n]", " ").replace("第1页", "")
                    .replace("\n", " ");
            String date = NHExtractDate(htmlText);
            if (date != null) {
                structureMap.put("病历日期", date);
                htmlText = htmlText.replace(date, "").trim();
            }
            List<String> titleContent = Lists.newArrayList(htmlText.split(" "));
            String title = titleContent.get(0);
            String jointTitle = titleContent.get(1);
            if (StringUtil.isNotBlank(title) && StringUtil.isNotBlank(jointTitle) && jointTitle.contains("医师查房记录")) {
                structureMap.put("病历标题", title + jointTitle);
                titleContent.remove(0);
                titleContent.remove(0);
            } else {
                structureMap.put("病历标题", recTitle);
                titleContent.remove(0);
            }
            StringBuffer sb = new StringBuffer();
            for (String text : titleContent) {
                sb.append(text).append(" ");
            }
            String content = sb.toString();
            if (content.contains("<img")) {
                String[] contentDoctor = content.split("<img");
                structureMap.put("病情记录", contentDoctor[0]);
                structureMap.put("记录医生", "<img" + contentDoctor[1]);
            } else {
                structureMap.put("病情记录", content);
            }
//            if (structureMap.containsKey("病情记录")) {
//                String info = structureMap.get("病情记录");
//                if (info.contains("医生签名")) {
//                    structureMap.put("病情记录", info.substring(0, info.lastIndexOf("医生签名")));
//                    structureMap.put("记录医生", "");
//                } else if (info.contains("医师签名")) {
//                    structureMap.put("病情记录", info.substring(0, info.lastIndexOf("医师签名")));
//                    structureMap.put("记录医生", "");
//                }
//            }
        }
    }

    /**
     * 抽取自定义病程录信息
     *
     * @param htmlText
     * @param structureMap
     */
    public static void extractWardInfo(String recTitle, String htmlText, Map<String, String> structureMap) {
        if (StringUtil.isNotBlank(htmlText)) {
            htmlText = htmlText.replaceAll("[   \n]", " ").replace("第1页", "")
                    .replace("\n", " ");
            String date = extractDate(htmlText);
            if (date != null) {
                structureMap.put("病历日期", date);
                htmlText = htmlText.replace(date, "").trim();
            }
            List<String> titleContent = Lists.newArrayList(htmlText.split(" "));
            String title = titleContent.get(0);
            if (StringUtil.isNotBlank(title) && title.equals(recTitle)) {
                structureMap.put("病历标题", title);
                titleContent.remove(0);
            } else {
                structureMap.put("病历标题", recTitle);
                structureMap.put("文书标题", title);
                if (titleContent.size() > 2) {
                    titleContent.remove(0);
                    titleContent.remove(0);
                }
            }
            StringBuffer sb = new StringBuffer();
            for (String text : titleContent) {
                sb.append(text).append(" ");
            }
            String content = sb.toString();
            if (content.contains("<img")) {
                String[] contentDoctor = content.split("<img");
                structureMap.put("病情记录", contentDoctor[0]);
                structureMap.put("记录医生", "<img" + contentDoctor[1]);
            } else {
                structureMap.put("病情记录", content);
            }
            if (structureMap.containsKey("病情记录")) {
                String info = structureMap.get("病情记录");
                if (info.contains("医生签名")) {
                    structureMap.put("病情记录", info.substring(0, info.lastIndexOf("医生签名")));
                    structureMap.put("记录医生", "");
                } else if (info.contains("医师签名")) {
                    structureMap.put("病情记录", info.substring(0, info.lastIndexOf("医师签名")));
                    structureMap.put("记录医生", "");
                }
            }
        }
    }

    /**
     * 替换值
     *
     * @param map
     * @param key
     * @param afterKey
     */
    public static void repKey(Map<String, String> map, String key, String afterKey) {
        if (StringUtil.isNotBlank(map.get(key))) {
            map.put(key, map.get(key).replaceAll(afterKey, ""));
        }
    }

    public static void makeEmpty(Map<String, String> structureMap, String... key) {
        for (String k : key) {
            if (structureMap.containsKey(k)) {
                structureMap.put(k, "");
            }
        }
    }
}
