<script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form';
import { useForm } from '@/hooks/web/useForm';
import { PropType, reactive, ref, watch, unref, nextTick } from 'vue';
import { useValidator } from '@/hooks/web/useValidator';
import { ROLE_TYPE_DICT_LIST, PRO_ROLE_PERMISSION_LIST } from '../constants';
import { getMenuTreeApi } from '@/api/common';
import { getRoleTreeApi } from '@/api/system/SysRole';
import { ElTree, ElCheckboxGroup, ElCheckbox } from 'element-plus';
import { forEach } from '@/utils/tree';
import { cloneDeep } from 'lodash-es';

const { required } = useValidator();

const { formRegister, formMethods } = useForm();
const { setValues, getFormData, getElFormExpose, setSchema } = formMethods;

const props = defineProps({
  currentRow: {
    type: Object as PropType<any>,
    default: () => null,
  },
  actionType: {
    type: String,
    default: 'add',
  },
});

const roleType = ref(props?.currentRow?.roleType ?? '1');

const menuRole: FormSchema = {
  hidden: roleType.value !== '1',
  field: 'menuRole',
  label: '角色权限',
  colProps: {
    span: 24,
  },
  formItemProps: {
    slots: {
      default: () => {
        return (
          <>
            <div class="flex w-full">
              <div class="flex-1">
                <ElTree
                  ref={treeRef}
                  show-checkbox
                  node-key="id"
                  highlight-current
                  check-strictly
                  expand-on-click-node={false}
                  data={treeData.value}
                  onNode-click={nodeClick}
                  props={defaultProps}
                >
                  {{
                    default: data => {
                      return <span>{data.data.nodeName}</span>;
                    },
                  }}
                </ElTree>
              </div>
              <div class="flex-1">
                {unref(currentTreeData) && unref(currentTreeData)?.permissionList ? (
                  <ElCheckboxGroup v-model={unref(currentTreeData).props.permission}>
                    {unref(currentTreeData)?.permissionList.map((v: any) => {
                      return <ElCheckbox label={v.value}>{v.label}</ElCheckbox>;
                    })}
                  </ElCheckboxGroup>
                ) : null}
              </div>
            </div>
          </>
        );
      },
    },
  },
};

const proRole: FormSchema = {
  hidden: roleType.value === '1',
  field: 'professionRole',
  label: '专业权限',
  colProps: {
    span: 24,
  },
  formItemProps: {
    slots: {
      default: () => {
        return (
          <>
            <div class="flex w-full">
              <div class="flex-1">
                <ElTree
                  ref={proRoleTreeRef}
                  show-checkbox
                  node-key="id"
                  highlight-current
                  check-strictly
                  expand-on-click-node={false}
                  data={proRoleTreeData.value}
                  onNode-click={proRoleNodeClick}
                  props={defaultProps}
                />
              </div>
              <div class="flex-1">
                {unref(currProRoleTreeData) && !unref(currProRoleTreeData)?.childs?.length ? (
                  <ElCheckboxGroup v-model={unref(currProRoleTreeData).props.permission}>
                    {PRO_ROLE_PERMISSION_LIST.map((v: any) => {
                      return <ElCheckbox label={v.value}>{v.label}</ElCheckbox>;
                    })}
                  </ElCheckboxGroup>
                ) : null}
              </div>
            </div>
          </>
        );
      },
    },
  },
};

/** 字符串转数组 */
const stringToArray = function (str: any) {
  if (str && typeof str === 'string') {
    return JSON.parse(str);
  }
  return [];
};

const treeRef = ref<typeof ElTree>();

const currentTreeData = ref();

const nodeClick = (treeData: any) => {
  // 因为permissionStr是字符串类型, 转数组
  const data = {
    ...treeData,
    permissionList: stringToArray(treeData?.props?.permissionStr),
  };
  currentTreeData.value = data;
};
const treeData = ref([]);

const getMenuList = async () => {
  const res = await getMenuTreeApi();
  if (res) {
    treeData.value = res;
    if (!props.currentRow) return;
    await nextTick();
    const checked: string[] = props.currentRow?.menuIds;
    unref(treeRef)?.setCheckedKeys(checked, false);
    // 按钮权限设置
    const btnPermission = props.currentRow?.btnPermission ?? {};
    if (Object.keys(btnPermission).length) {
      forEach(
        treeData.value,
        (item: any) => {
          const { props = {}, id } = item;
          if (btnPermission?.[id]?.length) {
            props.permission = btnPermission[id];
          }
        },
        defaultProps,
      );
    }
  }
};
getMenuList();

const defaultProps = {
  children: 'childs',
  label: 'nodeName',
};

const currProRoleTreeData = ref();

const proRoleTreeRef = ref<typeof ElTree>();
const proRoleTreeData = ref([]);

const proRoleNodeClick = (treeData: any) => {
  currProRoleTreeData.value = treeData;
};

const getProRoleList = async () => {
  const res = await getRoleTreeApi();
  if (res) {
    proRoleTreeData.value = res;
    if (!props.currentRow) return;
    await nextTick();
    const checked: string[] = props.currentRow?.professionIds;
    unref(proRoleTreeRef)?.setCheckedKeys(checked, false);
    // 角色按钮权限设置
    // 数据格式: proRolePermission{EAST-CQCS: "1", EAST-1104: "1"}
    const btnPermission = props.currentRow?.proRolePermission ?? {};
    if (Object.keys(btnPermission).length) {
      forEach(
        proRoleTreeData.value,
        (item: any) => {
          const { props = {}, id } = item;
          if (btnPermission?.[id] === '1') {
            props.permission = ['1'];
          }
        },
        defaultProps,
      );
    }
  }
};
getProRoleList();

const baseForm: FormSchema[] = [
  {
    field: 'id',
    label: '主键',
    component: 'Input',
    hidden: true,
  },
  {
    field: 'roleName',
    label: '角色名称',
    component: 'Input',
    componentProps: {},
  },
  {
    field: 'roleType',
    label: '角色类型',
    component: 'RadioButton',
    componentProps: {
      options: ROLE_TYPE_DICT_LIST,
      on: {
        change: val => {
          roleType.value = val;
          setSchema([
            {
              field: 'menuRole',
              path: 'hidden',
              value: roleType.value !== '1',
            },
            {
              field: 'professionRole',
              path: 'hidden',
              value: roleType.value === '1',
            },
          ]);
        },
      },
    },
    value: '1',
  },
  {
    field: 'remarks',
    label: '角色描述',
    component: 'Input',
    componentProps: {
      type: 'textarea',
    },
    colProps: {
      span: 24,
    },
  },
];

const formSchema = reactive<FormSchema[]>([...baseForm, menuRole, proRole]);

const rules = reactive({
  roleName: [required()],
});

const submit = async () => {
  const elForm = await getElFormExpose();
  const valid = await elForm?.validate().catch(err => {
    console.log(err);
  });
  if (valid) {
    const formData = await getFormData();
    const checkedKeys = unref(treeRef)?.getCheckedKeys() || [];
    formData.menuIds = checkedKeys || [];
    const checkedKeys1 = unref(proRoleTreeRef)?.getCheckedKeys() || [];
    formData.professionIds = checkedKeys1 || [];
    // 按钮权限
    const btnPermission = {};
    forEach(
      cloneDeep(unref(treeData)),
      (item: any) => {
        const { props = {}, id } = unref(item);
        const { permission = [] } = props;
        if (permission.length) {
          btnPermission[id] = cloneDeep(permission);
        }
      },
      defaultProps,
    );
    if (Object.keys(btnPermission).length) {
      formData.btnPermission = btnPermission;
    }
    // 系统组权限
    const proRolePermission = {};
    forEach(
      cloneDeep(unref(proRoleTreeData)),
      (item: any) => {
        const { props = {}, id } = unref(item);
        const { permission = [] } = props;
        if (permission.length) {
          proRolePermission[id] = cloneDeep(permission);
        }
      },
      defaultProps,
    );
    formData.proRolePermission = proRolePermission;
    return formData;
  }
};

watch(
  () => props.currentRow,
  currentRow => {
    if (!currentRow) return;
    setValues(currentRow);
  },
  {
    deep: true,
    immediate: true,
  },
);

defineExpose({
  submit,
});
</script>

<template>
  <Form :rules="rules" @register="formRegister" :schema="formSchema" />
</template>
