<script setup lang="ts">
import { ElMessage, FormInstance, FormRules } from "element-plus";
import { reactive, ref, watch, nextTick, computed } from "vue";
import { useNav } from "/@/layout/hooks/nav";
import { levelList } from "/@/utils/status";
import { menuType } from "./types";
import { useCompany } from "/@/hooks/core/useCompany";

import {
  httpAdd,
  httpUpdate,
  httpMenuAll,
  httpDetail
} from "/@/api/interest/role";

const { logout } = useNav();
const formSize = ref("small");

const ruleFormRef = ref<FormInstance>();

const { currentCompany } = useCompany();

const props = defineProps({
  itemId: {
    type: String,
    default: ""
  },
  showModel: {
    type: Boolean,
    default: false
  },
  isDetails: {
    type: String,
    default: "add"
  }
});
const showModelThis = ref(false);
const emit = defineEmits<{
  (e: "cancel"): void;
  (e: "refresh"): void;
}>();
const id = ref("");
const editType = ref("add");
const menuactionList = ref([]);
const action_list = ref([]);
const action_data_list = ref([]);
const private_data_list = ref([]);
const formModel = {
  roleid: "",
  role_name: "",
  level: "2",
  action: "",
  private_data: ""
};
const ruleForm = reactive<menuType>({ ...formModel });
const rules = reactive<FormRules>({
  role_name: [
    { required: true, message: "请输入角色名称", trigger: "blur" },
    { min: 2, max: 12, message: "长度在 2 到 12 个字符", trigger: "blur" }
  ],
  level: [
    {
      required: true,
      message: "请选择角色等级",
      trigger: "change"
    }
  ]
});
// 全选/全不选
const handleCheckAllChange = (checkAll, index, item, subIndex) => {
  menuactionList.value[index].child[subIndex].checkAll = checkAll;
  // this.$set(menuactionList.value, index, item);
  menuactionList.value[index].child[subIndex].action.forEach(element => {
    const findindex = menuactionList.value[index].child[
      subIndex
    ].checkList.findIndex(findItem => findItem === String(element.id));
    if (checkAll && findindex == -1) {
      menuactionList.value[index].child[subIndex].checkList.push(
        String(element.id)
      );
    } else if (!checkAll && findindex > -1) {
      menuactionList.value[index].child[subIndex].checkList.splice(
        findindex,
        1
      );
    }
  });
};
// 全选/全不选
const handleFieldAllChange = (fieldAll, index, item, subIndex) => {
  menuactionList.value[index].child[subIndex].fieldAll = fieldAll;
  // this.$set(menuactionList.value, index, item);
  menuactionList.value[index].child[subIndex].action_data.forEach(element => {
    const findindex = menuactionList.value[index].child[
      subIndex
    ].fieldList.findIndex(findItem => findItem === String(element.id));
    if (fieldAll && findindex == -1) {
      menuactionList.value[index].child[subIndex].fieldList.push(
        String(element.id)
      );
    } else if (!fieldAll && findindex > -1) {
      menuactionList.value[index].child[subIndex].fieldList.splice(
        findindex,
        1
      );
    }
  });
};
// 复选框组内的选中/不选中
const handleCheckedGroupChange = (event, index, item, subIndex) => {
  menuactionList.value[index].child[subIndex].checkAll = menuactionList.value[
    index
  ].child[subIndex].action.every(
    evitem =>
      menuactionList.value[index].child[subIndex].checkList.findIndex(
        finditem => finditem == evitem.id
      ) > -1
  );
  // this.$set(menuactionList.value, index, item);
};
// 复选框组内的选中/不选中
const handleFieldGroupChange = (event, index, item, subIndex) => {
  menuactionList.value[index].child[subIndex].fieldAll = menuactionList.value[
    index
  ].child[subIndex].action_data.every(
    evitem =>
      menuactionList.value[index].child[subIndex].fieldList.findIndex(
        finditem => finditem == evitem.id
      ) > -1
  );
  // this.$set(menuactionList.value, index, item);
};

// 单项复选框选中/不选中
const handleCheckedChange = (checked, id, index, subIndex, item) => {
  // console.log(checked, id, index, subIndex);
  if (checked) {
    // 选中时检查pid的选中状态
    menuactionList.value[index].child[subIndex].checkList.indexOf(id) == -1 &&
      menuactionList.value[index].child[subIndex].checkList.push(id);
  } else {
    const find = menuactionList.value[index].child[
      subIndex
    ].checkList.findIndex(e => e == id);
    if (find > -1) {
      menuactionList.value[index].child[subIndex].checkList.splice(find, 1);
    }
    menuactionList.value[index].child[subIndex].checkAll = false;
  }
  // this.$set(menuactionList.value, index, item);
};
// 单项复选框选中/不选中
const handleFieldChange = (checked, id, index, subIndex, item) => {
  // console.log(checked, id, index, subIndex);
  if (checked) {
    // 选中时检查pid的选中状态
    menuactionList.value[index].child[subIndex].fieldList.indexOf(id) == -1 &&
      menuactionList.value[index].child[subIndex].fieldList.push(id);
  } else {
    const find = menuactionList.value[index].child[
      subIndex
    ].fieldList.findIndex(e => e == id);
    if (find > -1) {
      menuactionList.value[index].child[subIndex].fieldList.splice(find, 1);
    }
    menuactionList.value[index].child[subIndex].fieldAll = false;
  }
  // this.$set(menuactionList.value, index, item);
  // console.log(menuactionList.value[index].child[subIndex]);
};
const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;

  if (!currentCompany.value.companyNo) {
    ElMessage.warning("请选择一个公司");
    return;
  }

  await formEl.validate(async (valid, fields) => {
    if (valid) {
      if (loading.value == true) return;
      loading.value = true;
      const { level, role_name, roleid } = ruleForm;

      action_list.value = []; // 字段数据
      action_data_list.value = []; // 功能数据
      private_data_list.value = [];
      console.log(menuactionList.value);
      menuactionList.value.forEach(x => {
        x.child.forEach(y => {
          action_list.value.push(...y.fieldList);
          action_data_list.value.push(...y.checkList);
          if (y.is_private_change == "1") {
            private_data_list.value.push(y.id);
          }
        });
      });
      if (action_data_list.value.length == 0) {
        ElMessage.error("请选择功能!");
        loading.value = false;
        return;
      }
      let model = {
        level,
        role_name,
        roleid,
        action: action_data_list.value, //按钮权限
        companyNo: currentCompany.value.companyNo,
        private_data: private_data_list.value //私有权限
      };

      if (editType.value == "add") {
        delete model["roleid"];
      }

      // if (!currentCompany.value.companyNo) {
      //   ElMessage.warning("请选择一个公司");
      //   return;
      // }

      const { code, message } =
        editType.value == "add"
          ? await httpAdd(model)
          : await httpUpdate(model);
      loading.value = false;
      if (code == 0) {
        ElMessage.success(titleType.value + "成功！");
        showModelThis.value = false;
        emit("refresh");
      } else if (code > 100 && code < 140) {
        showModelThis.value = false;
        logout();
      } else {
        ElMessage.error(message);
      }
    } else {
      console.log("error submit!", fields);
    }
  });
};
const resetForm = async (formEl: FormInstance | undefined, item) => {
  if (!formEl) return;
  formEl.clearValidate();
  formEl.resetFields();
  await nextTick(async () => {
    for (let key in ruleForm) {
      if (key == "role") {
        ruleForm[key] = item["roleid"] || "";
      } else {
        ruleForm[key] = item[key];
      }
    }
  });
};
const closeDialog = () => {
  showModelThis.value = false;
  emit("cancel");
};

const loading = ref(true);
const titleType = ref("");
async function initForm(item: Object) {
  loading.value = true;
  switch (editType.value) {
    case "add":
      titleType.value = "新建角色";
      break;
    case "edit":
      titleType.value = "编辑角色";
      break;
    case "view":
      titleType.value = "角色详情";
      break;
    default:
      titleType.value = "新建角色";
  }
  const { code, data, message } = await httpMenuAll({ level: "0,2" });
  if (code == 0) {
    let arr = JSON.parse(JSON.stringify(data ?? []));
    arr = arr.filter(item => item.child && item.child.length > 0);
    arr = arr.map(x => {
      x.child.map(y => {
        y.checkAll = false;
        y.checkList = [];
        y.fieldAll = false;
        y.fieldList = [];
        y.is_private_change = "0";
        if (y.is_private == "0") {
          y.private = [];
        } else {
          y.private = [
            {
              id: "0",
              label: "公有数据"
            },
            {
              id: "1",
              label: "私有数据"
            }
          ];
        }
        return y;
      });
      return x;
    });
    menuactionList.value = arr;
    // console.log(menuactionList.value);
  } else if (code > 100 && code < 140) {
    logout();
  } else {
    ElMessage.error(message);
  }
  await resetForm(ruleFormRef.value, item);
  if (editType.value !== "add") {
    await initData();
  }
  // console.log(ruleForm);
  loading.value = false;
}
const initData = async () => {
  const { code, data, message } = await httpDetail({ roleid: id.value });
  if (code == 0) {
    // action_list.value = [];
    // action_data_list.value = [];
    // private_data_list.value = [];
    const { action, action_data, private_data, role_name, level } = data ?? {};
    console.log(action ?? []);
    console.log(action_data);
    console.log(private_data);
    ruleForm.roleid = id.value;
    ruleForm.role_name = role_name ?? "";
    ruleForm.level = level ?? "1";
    action_list.value = action ?? [];
    action_data_list.value = action_data ?? [];
    private_data_list.value = private_data ?? [];
    console.log(action_list.value);
    console.log(action_data_list.value);
    console.log(private_data_list.value);

    const arr = JSON.parse(JSON.stringify(menuactionList.value));

    arr.map(x => {
      if (x.child && x.child.length > 0) {
        x.child.map(y => {
          if (y.action && y.action.length > 0) {
            y.action.map(z => {
              const Aindex =
                action_list.value.length > 0
                  ? action_list.value.findIndex(a => a == z.id)
                  : -1;
              if (Aindex !== -1) {
                y.checkList.push(action_list.value[Aindex]);
              }
              return z;
            });
            if (y.action.length == y.checkList.length) {
              y.checkAll = true;
            }
          }
          if (y.action_data && y.action_data.length > 0) {
            y.action.map(z => {
              const Bindex =
                action_data_list.value.length > 0
                  ? action_data_list.value.findIndex(a => a == z.id)
                  : -1;
              if (Bindex !== -1) {
                y.fieldList.push(action_data_list.value[Bindex]);
              }
              return z;
            });
            if (y.action_data.length == y.fieldList.length) {
              y.fieldAll = true;
            }
          }
          console.log(private_data_list.value);
          // console.log(y.private);
          if (y.private && y.private.length == 2) {
            let Cindex =
              private_data_list.value.length > 0
                ? private_data_list.value.findIndex(a => a == y.id)
                : -1;
            if (Cindex !== -1) {
              y.is_private_change = "1";
            } else {
              y.is_private_change = "0";
            }
          } else {
            y.is_private_change = "0";
          }
          return y;
        });
      }
      return x;
    });
    menuactionList.value = arr;
  } else if (code >= 100 && code <= 104) {
    logout();
  } else {
    ElMessage.warning(message);
  }
};
watch(
  () => {
    return props.showModel;
  },
  () => {
    const { showModel, itemId, isDetails } = props;
    showModelThis.value = showModel;
    if (showModelThis.value) {
      id.value = itemId;
      editType.value = isDetails;
      initForm(formModel);
    }
  }
);
let indeterminateCheck = computed(() => {
  return item => {
    // 选中子节点的数量
    const selectItemLength = item.action.filter(
      filitem =>
        item.checkList.findIndex(finditem => finditem == filitem.id) > -1
    ).length;
    // 未选中子节点的数量
    const noSlectItemLength = item.action.filter(
      filitem =>
        item.checkList.findIndex(finditem => finditem == filitem.id) == -1
    ).length;
    // // 当前节点的index
    // 存在选中子节点且存在未选中子节点为中间态
    return selectItemLength > 0 && noSlectItemLength > 0;
  };
});

let indeterminateField = computed(() => {
  return item => {
    // console.log(item);
    // 选中子节点的数量
    const selectItemLength = item.action_data.filter(
      filitem =>
        item.fieldList.findIndex(finditem => finditem == filitem.id) > -1
    ).length;
    // 未选中子节点的数量
    const noSlectItemLength = item.action_data.filter(
      filitem =>
        item.fieldList.findIndex(finditem => finditem == filitem.id) == -1
    ).length;
    // // 当前节点的index
    // 存在选中子节点且存在未选中子节点为中间态
    return selectItemLength > 0 && noSlectItemLength > 0;
  };
});
</script>

<template>
  <el-dialog
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    v-model="showModelThis"
    append-to-body
    center
    :top="'5vh'"
    :width="'900px'"
    :title="titleType"
    v-loading="loading"
    @close="closeDialog"
  >
    <el-form
      ref="ruleFormRef"
      :model="ruleForm"
      :rules="rules"
      label-width="90px"
      class="role-addedit"
      :size="formSize"
      status-icon
      v-loading="loading"
    >
      <el-row>
        <el-col :span="12">
          <el-form-item label="角色名称" prop="role_name">
            <el-input
              v-model="ruleForm.role_name"
              :disabled="editType == 'view'"
              placeholder="角色名称"
            /> </el-form-item
        ></el-col>
        <el-col :span="12">
          <el-form-item label="角色等级" prop="level">
            <el-select
              v-model="ruleForm.level"
              style="width: 100%"
              disabled
              placeholder="菜单类型"
            >
              <el-option
                v-for="(si, sii) in levelList"
                :key="'type' + si.value + sii"
                :label="si.label"
                :value="si.value"
              />
            </el-select> </el-form-item
        ></el-col>
        <el-col :span="24">
          <div class="quanxian-main">
            <div class="quanxian-title">
              <div style="color: #ff8888">*</div>
              <div>功</div>
              <div>能</div>
              <div>权</div>
              <div>限</div>
            </div>
            <div class="rule-view">
              <div class="rule-list">
                <el-row
                  v-for="(item, index) in menuactionList"
                  :key="'menu' + item.id + index"
                >
                  <el-col
                    v-if="item.child && item.child.length > 0"
                    class="ffff"
                    :span="24"
                  >
                    <div class="ftitle">
                      <div
                        v-for="(si, sii) in item.menu_name"
                        :key="'title' + sii + si"
                      >
                        {{ si }}
                      </div>
                    </div>
                    <div class="fbody">
                      <div
                        class="fbody-item"
                        v-for="(subItem, subIndex) in item.child"
                        :key="'yemian' + subItem.id + subIndex"
                      >
                        <template
                          v-if="
                            !(
                              subItem.action &&
                              subItem.action.length == 0 &&
                              subItem.action_data &&
                              subItem.action_data.length == 0
                            )
                          "
                        >
                          <div class="stitle clear">
                            <span class="_h2 fl">{{ subItem.menu_name }}</span>
                            <el-radio-group
                              style="margin: 0 0 0 20px"
                              class="fl"
                              size="small"
                              v-if="
                                subItem &&
                                subItem.private &&
                                subItem.private.length == 2
                              "
                              v-model="subItem.is_private_change"
                            >
                              <el-radio-button
                                size="small"
                                v-for="(radioN, ri) in subItem.private"
                                :key="radioN.label + ri"
                                :label="String(radioN.id)"
                                >{{ radioN.label }}</el-radio-button
                              >
                            </el-radio-group>
                          </div>
                          <div
                            class="scheck"
                            v-if="subItem.action && subItem.action.length > 0"
                          >
                            <div class="checkAll">
                              <el-checkbox
                                v-model="subItem.checkAll"
                                :disabled="editType == 'view'"
                                :indeterminate="indeterminateCheck(subItem)"
                                @change="
                                  handleCheckAllChange(
                                    $event,
                                    index,
                                    item,
                                    subIndex
                                  )
                                "
                                >功能全选</el-checkbox
                              >
                            </div>
                            <div class="checkItem">
                              <el-checkbox-group
                                v-model="subItem.checkList"
                                :disabled="editType == 'view'"
                                @change="
                                  handleCheckedGroupChange(
                                    $event,
                                    index,
                                    item,
                                    subIndex
                                  )
                                "
                              >
                                <el-checkbox
                                  :disabled="editType == 'view'"
                                  v-for="children in subItem.action"
                                  :key="'checkItem' + children.id"
                                  :label="String(children.id)"
                                  @change="
                                    handleCheckedChange(
                                      $event,
                                      String(children.id),
                                      index,
                                      subIndex,
                                      item
                                    )
                                  "
                                  >{{ children.action_name }}</el-checkbox
                                >
                              </el-checkbox-group>
                            </div>
                          </div>
                          <div
                            class="sfield"
                            v-if="
                              subItem.action_data &&
                              subItem.action_data.length > 0
                            "
                          >
                            <div class="checkAll">
                              <el-checkbox
                                v-model="subItem.fieldAll"
                                :disabled="editType == 'view'"
                                :indeterminate="indeterminateField(subItem)"
                                @change="
                                  handleFieldAllChange(
                                    $event,
                                    index,
                                    item,
                                    subIndex
                                  )
                                "
                                >字段全选</el-checkbox
                              >
                            </div>
                            <div class="checkItem">
                              <el-checkbox-group
                                v-model="subItem.fieldList"
                                :disabled="editType == 'view'"
                                @change="
                                  handleFieldGroupChange(
                                    $event,
                                    index,
                                    item,
                                    subIndex
                                  )
                                "
                              >
                                <el-checkbox
                                  v-for="children in subItem.action_data"
                                  :key="'FieldItem' + children.id"
                                  :label="String(children.id)"
                                  :disabled="editType == 'view'"
                                  @change="
                                    handleFieldChange(
                                      $event,
                                      String(children.id),
                                      index,
                                      subIndex,
                                      item
                                    )
                                  "
                                  >{{ children.field_name }}</el-checkbox
                                >
                              </el-checkbox-group>
                            </div>
                          </div>
                        </template>
                      </div>
                    </div>
                  </el-col>
                </el-row>
              </div>
            </div>
          </div>
        </el-col>
      </el-row>
      <el-col :span="24" class="clear">
        <el-button
          v-if="editType == 'add' || editType == 'edit'"
          type="primary"
          class="fr"
          :loading="loading"
          style="margin: 0 0 0 16px"
          @click="submitForm(ruleFormRef)"
          >保存</el-button
        >
        <el-button class="fr" style="margin: 0 0 0 16px" @click="closeDialog"
          >关闭</el-button
        >
      </el-col>
    </el-form>
  </el-dialog>
</template>
<style lang="scss" scoped>
.role-addedit {
  .quanxian-main {
    width: 100%;
    display: flex;

    .quanxian-title {
      width: 50px;
      position: relative;
      padding: 6px 0 0 7px;
      text-align: center;

      div {
        font-size: 14px;
        color: #606266;
        font-weight: 700;
      }
    }

    .rule-view {
      width: calc(100% - 50px);
      position: relative;
      height: 550px;
      overflow-y: scroll;
      border-top: 1px solid #dfe6ec;
      border-left: 1px solid #dfe6ec;

      // padding: 0 0 0 16px;
      .ffff {
        width: 100%;
        display: flex;
        align-items: stretch;

        .ftitle {
          width: 40px;
          text-align: center;
          border-right: 1px solid #dfe6ec;
          border-bottom: 1px solid #dfe6ec;
          padding: 10px 0;
          display: flex;
          align-items: center;
          flex-direction: column;
          justify-content: center;

          div {
            font-size: 17px;
            height: 22px;
            line-height: 22px;
            text-align: center;
            color: #97a8be;
          }
        }

        .fbody {
          width: calc(100% - 40px);
          border-right: 1px solid #dfe6ec;

          .fbody-item {
            // border-right: 1px solid #dfe6ec;
            border-bottom: 1px solid #dfe6ec;

            .stitle {
              padding: 15px 18px 10px 18px;
              border-bottom: 1px dashed #dfe6ec;
              font-size: 14px;
              color: #97a8be;

              ._h2 {
                display: inline-block;
                height: 24px;
                line-height: 24px;
              }
            }

            .scheck {
              padding: 15px 0 10px 0;
              display: flex;
              width: 100%;

              .checkAll {
                width: 110px;
                text-align: right;
                padding: 0 25px 0 0;
              }

              .checkItem {
                width: calc(100% - 120px);
              }
            }

            .sfield {
              padding: 0 0 10px 0;
              display: flex;
              width: 100%;

              .checkAll {
                width: 140px;
                text-align: right;
                padding: 0 35px 0 0;
              }

              .checkItem {
                width: calc(100% - 140px);
              }
            }
          }
        }
      }
    }
  }
}
</style>
