<template>
  <div>
    <div
      v-for="(item, index) in showList || []"
      :key="index"
      class="mx-4 mb-4 rounded-lg bg-white edit-healthy-file-item"
      :class="{
        'px-4': !props.isPlat,
        hidden: item.isHidden
      }"
    >
      <QuestionItem
        v-model:info="showList[index]"
        @checkMatrix="checkMatrix"
        @reply="reply"
      >
        <div class="px-4 my-2 text-right">
          <el-button
            v-if="item.isRepeat && item.showDelete"
            plain
            round
            size="small"
            type="danger"
            @click="repeatDelete(item, index)"
            >删除</el-button
          >
          <el-button
            v-if="item.isRepeat && item.showAdd"
            plain
            round
            size="small"
            type="primary"
            @click="repeat(item, index)"
            >新增</el-button
          >
        </div>
      </QuestionItem>
    </div>
    <div v-if="!props.isPlat" class="px-4">
      <el-button class="w-full" size="large" type="primary" @click="save"
        >保存并返回</el-button
      >
    </div>
    <div v-else>
      <el-button class="w-full" size="large" type="primary" @click="save"
        >保存</el-button
      >
    </div>
  </div>
</template>
<script lang="ts" setup>
import { computed, reactive, ref, inject, onMounted, nextTick } from "vue";
import QuestionItem from "./QuestionItem.vue";
import {
  parseJSON,
  request,
  deepClone,
  formatHistory,
  formatValidator,
  formatResultList,
  formatItemVal,
  formatData,
  formatQuKey
} from "@/utils";
import { useRoute, useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import * as question from "@/enums/question";
const route = useRoute();
const router = useRouter();
const props = defineProps({
  isPlat: {
    type: Boolean,
    default: false
  },
  indicator: {
    type: Object
  }
});

const emits = defineEmits(["update:value", "close"]);

const item = computed({
  get() {
    return props.indicator;
  },
  set(value) {
    emits("update:value", value);
  }
});

const rules = ref<any>({});

const state = reactive({
  detail: {
    key: "",
    validator: [] as any[],
    peg: {
      rules: {} as any,
      raw: ""
    },
    indicatorName: "",
    label: "",
    value: [] as any[],
    rawValue: [] as any[]
  }
});
const rawList = ref<any[]>([]);
const showList = ref<any[]>([]);
const testList = ref<any[]>([]);
const hideList = ref<any[]>([]);
const updateShowList = () => {
  showList.value = rawList.value.filter(
    (v: any) => !hideList.value.includes(v.sn)
  );
};
const reply = (item: any) => {
  console.log(item.type, item.attr, item, rules.value);
  // state.detail.value[getIdx(item.combination || item.attr)] =
  formatItemVal(item);

  const rule = rules.value[`QU${item.sn}`];
  console.log(rule);

  if (rule) {
    console.log(rule);
    console.log("规则执行");
    console.log("==================start=====================");
    let to: string | undefined = undefined;
    try {
      for (const i in rule || []) {
        console.log("执行规则", i + 1, "-----type:", rule[i].type);
        const res: any = formatRule(rule[i]) || {};
        switch (res.type) {
          case "show":
            console.log("show", res.target);
            hideList.value = hideList.value.filter(
              (v: string) => v != formatQuKey(res.target)
            );
            updateShowList();
            break;
          case "hide":
            console.log("hide", res.target);
            hideList.value.push(formatQuKey(res.target));
            updateShowList();
            break;
          case "to":
            to = res.to || undefined;
            break;
          case "say":
            // res.say && await pushText(res.say || '', 0, true)
            break;
          case "end":
            // state.replyLock = false
            return;
        }
      }
    } catch (e: any) {
      console.log("报错了");
      console.log(e);
      ElMessage.error(e?.message);
    }
  }
};
const archivesModule = ref<any>();
const init = async () => {
  console.log("props.indicator");
  console.log(props.indicator);
  archivesModule.value = deepClone(props.indicator);
  // document.title = "健康档案-" + archivesModule.value.name;
  archivesModule.value.extra.subjects = (
    archivesModule.value.extra?.subjects
      ? archivesModule.value.extra.subjects
      : [archivesModule.value.extra]
  )?.map((subject: any) => {
    const temp = {
      ...subject,
      ...parseJSON(subject.validator, {})
    };
    delete temp.validate;
    return temp;
  });
  // archivesModule.value.subjects =
  console.log(archivesModule.value.extra.subjects);

  rawList.value = formatValidator(archivesModule.value.extra.subjects || []);
  console.log("rawList", rawList.value);

  // const historyAnswer = parseJSON(archivesModule.value.archivesIndicator.extraTemplateRawValue)
  formatHistory(1, rawList);
  console.log("historyAnswer", rawList.value);
  const rule = parseJSON(archivesModule.value.extra?.peg)?.rules || {};
  console.log("rule", rule);
  rules.value = rule;
  rawList.value.forEach(reply);
  updateShowList();
};

onMounted(init);
// 矩阵题选择
const checkMatrix = (item: any, rowIdx: number, colIdx: number) => {
  console.log(item);

  const curState = item.matrix[rowIdx][colIdx];
  const isMultiple = item.isMultiple;
  const mutuallyExclusive = item.columns[colIdx].mutuallyExclusive;
  // 单选
  if (!isMultiple) {
    item.matrix[rowIdx].forEach((v: any, k: number) => {
      item.matrix[rowIdx][k] = k === colIdx ? !curState : false;
    });
  } else {
    // 多选
    // 该列有互斥
    if (mutuallyExclusive) {
      if (curState) {
        item.matrix[rowIdx][colIdx] = !curState;
      } else {
        item.matrix[rowIdx].forEach((v: any, k: number) => {
          item.matrix[rowIdx][k] = k === colIdx;
        });
      }
    } else {
      item.matrix[rowIdx].forEach((v: any, k: number) => {
        if (item.columns[k].mutuallyExclusive) {
          item.matrix[rowIdx][k] = false;
        }
      });
      item.matrix[rowIdx][colIdx] = !item.matrix[rowIdx][colIdx];
    }
  }
  const res: string[] = [];
  item.matrix?.forEach((cols: boolean[], k1: number) => {
    cols &&
      cols.forEach &&
      cols?.forEach((c: boolean, k2: number) => {
        c && res.push(item.rows[k1].label + "" + item.columns[k2].label);
      });
  });
  item.value = res;
};
const getRuleKey = (type: string) => {
  switch (type) {
    case "showHide":
    case "to":
      return "expression";
    case "say":
    case "replace":
      return "keyword";
    default:
      return "";
  }
};

const getItem = (code: string) => {
  code = code.replace(/^QU/, "");
  return rawList.value.find((v: any) => v.sn === code);
};
const getQ = (code: string) => {
  code = code.replace(/^QU/, "");
  const items = showList.value.filter((v: any) => v.sn === code);
  const item = getItem(code);
  console.log(showList.value);
  console.log(items);
  if (items.length > 1) {
    return items.map(formatItemVal);
  }
  const val = item.value;

  if (item.type === question.QUESTION_TYPE_RADIO) {
    return [val];
  } else if (item.type === question.QUESTION_TYPE_CHECKBOX) {
    return val || [];
  }
  return item.value;
};
const getVal = (code: string) => {
  return getQ(code);
};
const formatAge = (birthday: string) => {
  if (!birthday) return "";
  if (!isNaN(Number(birthday))) return birthday;
  const offset = +new Date() - +new Date(birthday.replace(/-/g, "/"));
  return parseInt(String(offset / 86400000 / 365));
};
const chooseAnd = (itemVal: number[], ...choices: number[]) => {
  for (const idx of choices) {
    if (!itemVal.includes(idx)) return false;
  }
  return true;
};
const chooseOr = (itemVal: number[], ...choices: number[]) => {
  for (const idx of choices) {
    if (itemVal.includes(idx)) return true;
  }
  return false;
};
const chooseMatrix = (itemVal: string[], ...values: string[]) => {
  for (const v of values) {
    if (!itemVal.includes(v)) return false;
  }
  return true;
};
const chooseMatrixOr = (itemVal: string[], ...values: string[]) => {
  for (const v of values) {
    if (!itemVal.includes(v)) return true;
  }
  return false;
};
const isEmpty = (val: any) => {
  if (Array.isArray(val)) {
    return !val.length;
  }
  if (val === 0) return false;
  return !val;
};
const count = (arg: any[] | string) =>
  typeof arg == "number" ? arg : arg.length;
const customFunc = [
  "formatAge",
  "chooseAnd",
  "chooseOr",
  "chooseMatrix",
  "chooseMatrixOr",
  "isEmpty",
  "count"
];
[
  formatAge,
  chooseAnd,
  chooseOr,
  chooseMatrix,
  chooseMatrixOr,
  isEmpty,
  count
].forEach((fn, i) => {
  window[customFunc[i]] = fn;
});
const formatRule = (rule: any) => {
  const getQAReg = new RegExp(/QU(\w+)?/gi);
  let rawCondition = rule[getRuleKey(rule.type)] || "";
  rawCondition = rawCondition
    .replace(/ and /g, " && ")
    .replace(/ or /g, " || ");

  let condition = rawCondition;
  let replaceReg: RegExp | undefined = undefined;
  let qa = [];
  if (condition) {
    console.log(
      `%c当前的规则： ${condition}`,
      "font-size: 16px; color: #4b72f6;"
    );
    qa = rawCondition.match(getQAReg) || [];
    console.log("qa:", qa.join(","));
    qa.map((n: string) => {
      const code = formatQuKey(n);
      const curItem = getItem(code);
      const v = getVal(code);
      console.log(`当前拿到的值`, v);
      for (const func of customFunc) {
        if (condition.includes(func)) {
          // 选择类方法
          if (/^choose/.test(func)) {
            if (func.includes("Matrix")) {
              curItem.rows.forEach((row: any) => {
                curItem.columns.forEach((col: any) => {
                  const matrixAttr = row.attr + col.attr;
                  if (condition.includes(matrixAttr)) {
                    condition = condition.replace(
                      new RegExp(matrixAttr),
                      `"${row.label + col.label}"`
                    );
                  }
                });
              });
            } else {
              let sortChoices = curItem.choices.map((v: any, k: number) => {
                return {
                  ...v,
                  index: k
                };
              });
              sortChoices = sortChoices.sort(
                (a: any, b: any) => b.attr.length - a.attr.length
              );
              sortChoices.forEach((v: any) => {
                if (condition.includes(v.attr)) {
                  condition = condition.replace(new RegExp(v.attr), v.index);
                }
              });
            }
          }
        }
      }
      const reg = new RegExp(n);
      console.log(`要执行的正则`, reg, v);
      condition = condition.replace(
        reg,
        Array.isArray(v)
          ? `[${v
              .map(v2 => (typeof v2 === "string" ? `'${v2}'` : v2))
              .join(",")}]`
          : typeof v === "string"
          ? `'${v}'`
          : v
      );
      console.log(condition);
    });

    console.log(`获取到的qa`, qa);
    console.log(`最后的condition`, condition);
  }
  let flag = false;
  try {
    flag = eval(condition);
  } catch (e) {
    flag = false;
  }
  console.log(`当前规则执行的flag: %c ${flag}`, "color: #f00;");

  // eslint-disable-next-line no-case-declarations
  switch (rule.type) {
    case "showHide":
      console.log(`执行---------------show hide -----------规则: ${condition}`);
      if (rule.method == "show") {
        return {
          type: flag ? "show" : "hide",
          target: rule.question
        };
      } else {
        return {
          type: !flag ? "show" : "hide",
          target: rule.question
        };
      }
    case "to":
      console.log(`执行---------------to-----------规则: ${condition}`);
      return flag
        ? {
            type: "to",
            to: rule.to
          }
        : undefined;
    case "say":
      console.log(`执行---------------say-----------规则: ${condition}`);
      // flag && pushText(rule.say)
      if (flag) {
        return {
          type: "say",
          say: rule.say
        };
      }
      break;

    case "replace":
      console.log(`执行---------------replace-----------规则: ${condition}`);
      replaceReg = new RegExp(rule.keyword);
      console.log(`执行正则: ${rule.keyword}`);

      {
        let t = undefined;
        //  存在index时
        const q = getItem(rule.from);
        console.log(`当前replace-q: `);
        console.log(q);
        if (rule.index >= 0) {
          console.log(q["choices"][rule.index - 1]);
          t = q["choices"][rule.index - 1]?.label;
        } else {
          if (q["choices"]) {
            t = q["choices"][Number(getItem(rule.from))].label;
          } else {
            t = q.value;
          }
        }
        console.log(`获取到的t: ${t}`);

        getItem(rule.to).title = getItem(rule.to).title?.replace(
          replaceReg,
          Array.isArray(t) ? t.join(",") : t
        );
      }
      break;
    case "end":
      return {
        type: "end"
      };
  }
};

const repeat = (item: any, idx: number) => {
  console.log("repeat", item);
  const showDelete = showList.value.filter(
    (v: any) => v.attr === item.attr
  ).length;
  showList.value.forEach((v: any) => {
    if (v.attr === item.attr) {
      v.showDelete = showDelete;
      v.showAdd = false;
    }
  });
  nextTick(() => {
    const item = JSON.parse(JSON.stringify(showList.value.at(idx)));
    if (item.type === "group" || item.type === "combination") {
      item.children = item.children.map((v: any) => {
        v.value = Array.isArray(v.value) ? [] : "";
        return v;
      });
    }
    showList.value.splice(idx + 1, 0, {
      ...item,
      showDelete,
      isAnswered: false,
      showAdd: true,
      value: ""
    });
  });
};
const repeatDelete = (item: any, idx: number) => {
  showList.value.splice(idx, 1);
  const showDelete =
    showList.value.filter((v: any) => v.attr === item.attr).length > 1;
  if (item.showAdd && showList.value[idx - 1]) {
    showList.value[idx - 1].showAdd = true;
  }
  showList.value.forEach((v: any) => {
    if (v.attr === item.attr) {
      v.showDelete = !!showDelete;
    }
  });
};
const close = () => {
  emits("close");
};
const submitSimpleFormData = inject("submitSimpleFormData") as Function;
const save = async () => {
  console.log("showList", showList.value);
  const list: any[] = formatResultList(showList.value);
  console.log(list);
  const answers = formatData(list, props.indicator);
  console.log("answers", answers);
  submitSimpleFormData && submitSimpleFormData(answers, close);
};
</script>
<style lang="scss"></style>
