<script setup lang="ts">
import { nextTick, onMounted, ref, useTemplateRef, watch } from 'vue';
import { message } from 'ant-design-vue';

import ConfirmModal from '@/components/ConfirmModal.vue';
import OrganizationalStructure from '@/components/OrganizationalStructure.vue';
import SvgIcon from '@/components/SvgIcon.vue';
import { useRequest } from '@/hooks/request';
import { useUserInfoStore } from '@/stores/user-info';
import { t } from '@/i18n';
import {
  addCharacter,
  addDevicePermissions,
  addGrantRolePermissions,
  deleteCharacter,
  getAllGroupList,
  getFindRolesByOrgIds,
  getPermissionCheckTree,
  getSubOrgsByToken,
  updateCharacter,
} from '@/api';
import { OperatePermission } from '@/utils/permission-type';

import type { DataNode, TreeProps } from 'ant-design-vue/es/tree';
import type { Key } from 'ant-design-vue/es/vc-tree/interface';
import type { CheckInfo } from 'ant-design-vue/es/vc-tree/props';
import type { OperationPermissions, TreeStructure } from '@/types';

interface HaracterItem {
  name: string;
  id?: number;
  show: boolean;
}

const { booleanPermission } = useUserInfoStore();
const characterList = ref<HaracterItem[]>([]);
const { handleRequest } = useRequest();
const characterListId = ref();
const inputRef = ref<HTMLInputElement[]>([]); // 明确的类型声明
const permissions = ref<string>('dataPermissions');
const equipmentChecked = ref<boolean>(false);
const editorChecked = ref<boolean>(true);
// const valueTime = ref<string>('1');
const operationpermissions = ref<OperationPermissions[]>([]);
const devicePermissionsExpandedKeys = ref<number[]>([]);
const checkedFatherKeys = ref<number[]>([]);

const devicePermissionsCheckedKeys = ref({
  checked: [] as number[], // 完全选中的节点
  halfChecked: [] as number[], // 半选中的节点（在严格模式下通常为空）
});
const allKeys = ref<number[]>([]);
const indeterminate = ref<boolean>(false);
const orgId = ref<number>();
const characterId = ref<number>();
const enterShow = ref<boolean>(false);
const modalComponentRef = useTemplateRef('modalComponent');
const expandedKeys = ref<number[]>([]);
const checkedKeys = ref<number[]>([]);
const treeStructure = ref<DataNode[]>([]);
const fieldNamesCheck: TreeProps['fieldNames'] = {
  children: 'subPermissions',
  title: 'menuName',
  key: 'id',
};
const pagePermissionsTree = ref<DataNode[]>([]);
const fieldNames: TreeProps['fieldNames'] = {
  children: 'deviceGroupChilds',
  title: 'groupName',
  key: 'id',
};

const addCharacterName = async () => {
  if (characterList.value.some((item) => !isValidString(item.name))) {
    return;
  }
  characterList.value.push({
    name: '',
    id: undefined,
    show: true,
  });
  await nextTick();

  inputRef.value[0].focus();
};
const clickCharacter = (id: number) => {
  if (characterList.value.some((item) => !isValidString(item.name))) {
    return;
  }
  characterListId.value = id;
  getDeviceGroupList();
  getFunctionPermList();
};
const addEditor = async (index: number) => {
  if (characterList.value.some((item) => !isValidString(item.name))) {
    return;
  }
  characterList.value[index].show = true;
  await nextTick();
  inputRef.value[0].focus();
};
const addDelete = (id: number | undefined) => {
  if (!id) {
    return message.warning(t('deviceList.pleaseSelectItemDelete'));
  }
  if (characterList.value.some((item) => !isValidString(item.name))) {
    return;
  }
  characterId.value = id;
  modalComponentRef.value?.showView();
};
const confirm = () => {
  handleRequest(async () => {
    if (characterId.value) {
      await deleteCharacter(characterId.value);
      message.success(t('common.deleteSuccess'));
      if (orgId.value) {
        getFindRolesByOrg(orgId.value);
      }
    }

    modalComponentRef.value?.hideView();
  });
};
const editorCharacterBlur = (index: number, name: string) => {
  if (!enterShow.value) {
    editorCharacter(index, name);
  }
};
/**
 * 校验字符串是否非空且不包含任何空白字符
 * @param str 待检测的字符串
 * @returns 是否有效（非空且无空白）
 */
const isValidString = (str: string): boolean => {
  return /^[\S]+$/.test(str);
  // ^ 开头 | \S 非空白字符 | + 至少一个 | $ 结尾
};
const editorCharacter = (index: number, name: string) => {
  if (name) {
    if (isValidString(name)) {
      enterShow.value = true;
      characterList.value[index].show = false;
      const id = characterList.value[index].id;
      handleRequest(async () => {
        if (id) {
          await updateCharacter({ roleName: name, orgId: orgId.value, id });
          message.success(t('common.editSuccess'));
        } else {
          await addCharacter({ roleName: name, orgId: orgId.value });
          message.success(t('common.addSuccess'));
        }
        enterShow.value = false;
        if (orgId.value) {
          getFindRolesByOrg(orgId.value);
        }
      });
    } else {
      return message.warning(t('roleManage.nameCannotContainSpaces'));
    }
  } else {
    return message.warning(t('roleManage.nameCannotBeEmpty'));
  }
};
const editorPermission = () => {
  editorChecked.value = false;
};
const cancelPermission = () => {
  if (permissions.value === 'dataPermissions') {
    getDeviceGroupList();
  } else {
    getFunctionPermList();
  }
  editorChecked.value = true;
};

const addTree = (checked: Key[] | { checked: Key[]; halfChecked: Key[] }, info: CheckInfo) => {
  if (info.node.parent) {
    checkedFatherKeys.value.push(info.node.parent.node.id);
  }
};

const savePermission = () => {
  if (permissions.value === 'dataPermissions') {
    handleRequest(async () => {
      await addDevicePermissions({
        roleId: characterListId.value,
        groupIds: devicePermissionsCheckedKeys.value.checked,
      });
      getDeviceGroupList();
    });
  } else {
    let data: number[] = [];
    operationpermissions.value.forEach((item) => {
      if (item.list.length) {
        data = [...new Set([...data, ...item.list])];
      }
    });

    handleRequest(async () => {
      if (!checkedKeys.value.length) {
        checkedFatherKeys.value = [];
      }
      await addGrantRolePermissions({
        roleId: characterListId.value,
        permissionIds: [...new Set([...checkedKeys.value, ...checkedFatherKeys.value, ...data])],
      });
      getFunctionPermList();
    });
  }
  editorChecked.value = true;
};
const clickOrganizationChange = (id: number) => {
  orgId.value = id;
  getFindRolesByOrg(id);
};

const getFindRolesByOrg = (id: number) => {
  handleRequest(async () => {
    const data = await getFindRolesByOrgIds([id]);
    characterList.value = [];
    if (data.length) {
      data.forEach((item) => {
        const { roleName, id } = item;
        characterList.value.push({
          name: roleName,
          id,
          show: false,
        });
      });
      if (!characterListId.value) {
        characterListId.value = data[0].id;
        getDeviceGroupList();
        getFunctionPermList();
      } else {
        getDeviceGroupList();
        getFunctionPermList();
      }
    } else {
      pagePermissionsTree.value = [];
      treeStructure.value = [];
      operationpermissions.value = [];
    }
  });
};

const getDeviceGroupList = () => {
  handleRequest(async () => {
    const list = await getAllGroupList({
      roleId: undefined,
    });
    const data = await getAllGroupList({
      roleId: characterListId.value,
    });
    devicePermissionsExpandedKeys.value = [];
    devicePermissionsCheckedKeys.value.checked = [];
    allKeys.value = [];
    list.forEach((item) => {
      item.key = item.id;
      allKeys.value.push(item.id);
      devicePermissionsExpandedKeys.value.push(item.id);
      if (item.deviceGroupChilds.length) {
        item.deviceGroupChilds.forEach((i) => {
          i.key = i.id;
          allKeys.value.push(i.id);
        });
      }
    });

    data.forEach((item) => {
      devicePermissionsCheckedKeys.value.checked.push(item.id);
      item.deviceGroupChilds.forEach((i) => {
        devicePermissionsCheckedKeys.value.checked.push(i.id);
      });
    });

    pagePermissionsTree.value = list as DataNode[];
  });
};
const transformTreeData = (data: TreeStructure[]): DataNode[] => {
  return data.map((item) => ({
    ...item,
    key: item.id, // 关键：将 id 映射到 key
    title: item.menuName,
    children: item.subPermissions ? transformTreeData(item.subPermissions) : undefined,
  }));
};

const transformData = (data: TreeStructure[]): OperationPermissions[] => {
  return data.map((item) => {
    // 转换当前层级的属性
    const transformed = {
      value: item.id,
      label: item.menuName,
      list: item.subPermissions?.filter((sub) => sub.checked === 1).map((sub) => sub.id) || [],
      ...item,
      // 保留其他属性（如果需要）
      ...(item.subPermissions && {
        subPermissions: transformData(item.subPermissions),
      }),
    };

    return transformed;
  });
};

const getFunctionPermList = () => {
  handleRequest(async () => {
    // const data = await getSubPermList(0);
    const dataCheck = await getPermissionCheckTree(characterListId.value);
    checkedKeys.value = [];
    expandedKeys.value = [];
    if (dataCheck.length) {
      treeStructure.value = transformTreeData(dataCheck[0].subPermissions[0].subPermissions);
      operationpermissions.value = transformData(dataCheck[0].subPermissions[1].subPermissions);
      dataCheck[0].subPermissions[0].subPermissions.forEach((item) => {
        if (item.subPermissions) {
          item.subPermissions.forEach((i) => {
            if (i.checked === 1) {
              checkedKeys.value.push(i.id);
            }
          });
          expandedKeys.value.push(item.id);
        } else {
          if (item.checked === 1) {
            checkedKeys.value.push(item.id);
          }
        }
      });
    }
  });
};

const selectAll = () => {
  indeterminate.value = false;
  if (equipmentChecked.value) {
    devicePermissionsCheckedKeys.value.checked = allKeys.value;
  } else {
    devicePermissionsCheckedKeys.value.checked = [];
  }
};

const addRadioGroup = () => {
  if (permissions.value === 'functionPermissions') {
    getDeviceGroupList();
  } else {
    getFunctionPermList();
  }
  editorChecked.value = true;
};

watch(
  () => devicePermissionsCheckedKeys.value.checked,
  (count) => {
    if (count) {
      indeterminate.value = !!count.length && count.length < allKeys.value.length;
      equipmentChecked.value = count.length === allKeys.value.length;
    }
  },
);

onMounted(() => {
  handleRequest(async () => {
    await getSubOrgsByToken();
    getFunctionPermList();
  });
});
</script>

<template>
  <div>
    <div class="text-top">{{ t('navigation.roleManage') }}</div>
    <AFlex>
      <OrganizationalStructure @change="clickOrganizationChange" />
      <div class="content">
        <AFlex justify="space-between" align="center" class="content-top">
          <div class="content-text">{{ t('userManage.role') }}</div>
          <div
            class="icon-style pointer"
            @click="addCharacterName"
            v-if="booleanPermission(OperatePermission.新增角色)"
          >
            <AFlex align="center"
              ><SvgIcon name="plus" />
              <div class="text-left">{{ t('common.add') }}</div>
            </AFlex>
          </div>
        </AFlex>
        <div>
          <div v-for="(item, index) in characterList" :key="index">
            <div class="character-input" v-if="item.show">
              <AInput
                class="input-heught"
                v-model:value="item.name"
                :bordered="false"
                ref="inputRef"
                @pressEnter="editorCharacter(index, item.name)"
                @blur="editorCharacterBlur(index, item.name)"
              />
            </div>
            <AFlex
              v-else
              justify="space-between"
              align="center"
              :class="item.id === characterListId ? 'character-list character-list-color' : 'character-list'"
            >
              <div class="pointer text-height" @click="clickCharacter(item.id!)">{{ item.name }}</div>
              <div v-if="item.id === characterListId">
                <SvgIcon
                  v-if="booleanPermission(OperatePermission.编辑角色)"
                  class="pointer"
                  name="edit-o"
                  @click="addEditor(index)"
                />
                <SvgIcon
                  v-if="booleanPermission(OperatePermission.删除角色)"
                  class="pointer icon-left"
                  @click="addDelete(item.id)"
                  name="delete"
                />
              </div>
            </AFlex>
          </div>
        </div>
      </div>

      <div class="permission-management">
        <AFlex justify="space-between" align="center" class="content-top">
          <div class="content-text">{{ t('roleManage.permission') }}</div>
          <div
            class="pointer"
            @click="editorPermission"
            v-if="editorChecked && booleanPermission(OperatePermission.编辑角色)"
          >
            <AFlex align="center"
              ><SvgIcon name="edit-o" />
              <div class="text-left">{{ t('common.editor') }}</div>
            </AFlex>
          </div>
          <AFlex v-if="!editorChecked">
            <div class="pointer" @click="cancelPermission">
              <AFlex align="center"
                ><SvgIcon name="close" />
                <div class="text-left">{{ t('common.cancel') }}</div>
              </AFlex>
            </div>
            <div class="pointer pointer-left" @click="savePermission">
              <AFlex align="center"
                ><SvgIcon name="save" />
                <div class="text-left">{{ t('common.save') }}</div>
              </AFlex>
            </div>
          </AFlex>
        </AFlex>

        <ARadioGroup v-model:value="permissions" button-style="solid" size="large" @change="addRadioGroup">
          <ARadioButton value="dataPermissions">{{ t('roleManage.dataPermission') }}</ARadioButton>
          <ARadioButton value="functionPermissions">{{ t('roleManage.functionalPermission') }}</ARadioButton>
        </ARadioGroup>
        <div v-if="permissions === 'dataPermissions'">
          <AFlex align="center" class="device-permissions">
            <ACheckbox
              class="select-all"
              v-model:checked="equipmentChecked"
              :indeterminate="indeterminate"
              :disabled="editorChecked"
              @change="selectAll"
              >{{ t('roleManage.deviceGroupPermission') }}</ACheckbox
            >
          </AFlex>
          <div class="permission-div">
            <ATree
              v-model:expanded-keys="devicePermissionsExpandedKeys"
              v-model:checked-keys="devicePermissionsCheckedKeys"
              :tree-data="pagePermissionsTree"
              checkable
              default-expand-all
              :field-names="fieldNames"
              :disabled="editorChecked"
              :check-strictly="true"
            />
          </div>

          <!-- <AFlex align="center" class="device-permissions div-top">
            <ACheckbox class="select-all" :disabled="editorChecked" v-model:checked="equipmentChecked"
              >启用时间查询颗粒度设置</ACheckbox
            >
          </AFlex>
          <ARadioGroup v-model:value="valueTime" name="radioGroup" class="radio-group" :disabled="editorChecked">
            <ARadio value="1">分钟</ARadio>
            <ARadio value="2">小时</ARadio>
            <ARadio value="3">天</ARadio>
            <ARadio value="4">月</ARadio>
          </ARadioGroup> -->
        </div>
        <div v-if="permissions === 'functionPermissions'">
          <AFlex align="center" class="device-permissions">
            <div>{{ t('roleManage.viewPermission') }}</div>
          </AFlex>
          <div class="check-div">
            <ATree
              v-model:expanded-keys="expandedKeys"
              v-model:checked-keys="checkedKeys"
              :tree-data="treeStructure"
              checkable
              :field-names="fieldNamesCheck"
              :disabled="editorChecked"
              class="tree-permissions"
              default-expand-all
              @check="addTree"
            />
          </div>

          <AFlex align="center" class="device-permissions div-top">
            <div>{{ $t('roleManage.operationPermission') }}</div>
          </AFlex>
          <div class="operation">
            <AFlex align="center" v-for="(item, index) in operationpermissions" :key="index" class="operation-div">
              <ACheckboxGroup v-model:value="item.list" :options="item.subPermissions" :disabled="editorChecked" />
            </AFlex>
          </div>
        </div>
      </div>
    </AFlex>
    <ConfirmModal
      ref="modalComponent"
      :title="t('common.deleteConfirmation')"
      :description-text="t('common.confirmDeletion')"
      :icon="{ name: 'delete' }"
      :icon-bg-color="'#F56C6C'"
      @confirm="confirm"
    />
  </div>
</template>

<style lang="scss" scoped>
.operation {
  height: 200px;
  overflow: auto;
}

.operation-div {
  width: 100%;
  height: 48px;
  padding-left: 52px;
  border-bottom: 1px solid #e4e7ed;
}

.check-div {
  height: calc(100vh - 494px);
  overflow: auto;
}

.permission-div {
  height: calc(100vh - 244px);
  overflow: auto;
}

.pointer-left {
  margin-left: 24px;
}

:deep(.permission-management) {
  .ant-tree-list-holder-inner > div {
    display: flex;
    align-items: center;
    width: 100%;
    height: 48px;
    padding-left: 26px;
  }

  .tree-permissions .ant-tree-list-holder-inner > div {
    border-bottom: 1px solid #e4e7ed;
  }

  .ant-tree-list-holder-inner > div > .ant-tree-checkbox {
    margin-block-start: 0;
  }

  .ant-tree-list-holder-inner > div > .ant-tree-switcher > span {
    margin-top: 16px;
  }
}

.radio-group {
  margin-top: 13px;
  margin-left: 48px;
}

:deep(.radio-group) {
  .ant-radio-wrapper {
    margin-inline-end: 20px;
  }
}

.device-permissions {
  width: 100%;
  height: 48px;
  padding-left: 24px;
  margin-top: 16px;
  background: #f5f7fa;
  border-radius: 4px;
}

.permission-management .div-top {
  margin-top: 0;
}

.permission-management {
  width: 100%;
  height: calc(100vh - 80px);
  padding: 16px;
  background: #fff;
  border-radius: 16px;
}

.input-heught {
  height: 38px;
}

.character-input {
  width: 214px;
  height: 40px;
  background: rgb(255 255 255 / 15%);
  border: 1px solid var(--antd-color-primary);
  border-radius: 4px;
}

.text-left {
  margin-left: 10px;
}

.icon-style {
  color: var(--antd-color-primary);
}

.text-height {
  height: 40px;
  line-height: 40px;
}

.icon-left {
  margin-left: 13px;
}

.pointer {
  cursor: pointer;
}

.character-list {
  width: 214px;
  height: 40px;
  padding: 0 12px;
  font-size: 14px;
  font-style: normal;
  font-weight: 400;
  line-height: 22px;
  color: #000;
  text-align: left;
  border-radius: 4px;
}

.character-list-color {
  color: var(--antd-color-primary);
  background: var(--antd-color-primary-opacity-15);
}

.content-top {
  margin-bottom: 16px;
}

.button-style {
  color: var(--antd-color-primary);
}

.content-text {
  font-size: 16px;
  font-style: normal;
  font-weight: 600;
  line-height: 24px;
  color: #333;
  text-align: left;
}

.content {
  width: 246px;
  height: calc(100vh - 80px);
  padding: 16px;
  margin-right: 16px;
  background: #fff;
  border-radius: 16px;
}

.text-top {
  margin-bottom: 16px;
  font-size: 20px;
  font-style: normal;
  font-weight: 500;
  line-height: 32px;
  color: rgb(0 0 0 / 85%);
  text-align: left;
}
</style>
