<template>
  <div>
    <Breadcrumb :items="['权限管理', '账号管理']" :title="'账号管理'" />
    <div class="container">
      <a-row :gutter="20" align="stretch">
        <a-col :span="24">
          <a-card class="general-card" style="min-height: 80vh">
            <template #title>
              <a-row>
                <a-col :flex="1">
                  <a-form
                    :model="filterForm"
                    :label-col-props="{ span: 6 }"
                    :wrapper-col-props="{ span: 18 }"
                    label-align="left"
                    auto-label-width
                  >
                    <a-row :gutter="[16, 16]">
                      <a-col :xxl="5" :xl="8" :lg="8" :md="12" :sm="24">
                        <a-form-item
                          field="keyword"
                          label="模糊匹配"
                          :no-style="true"
                          ><a-input-search
                            v-model="filterForm.keyword"
                            placeholder="根据用户名称模糊匹配"
                            allow-clear
                            @search="filterUser()"
                            @clear="filterUser()"
                            @keyup.enter="filterUser()"
                          />
                        </a-form-item>
                      </a-col>
                      <a-col :xxl="5" :xl="8" :lg="8" :md="12" :sm="24">
                        <a-form-item
                          field="groupId"
                          label="区域范围"
                          row-class="mb0"
                        >
                          <a-tree-select
                            v-model="filterForm.groupId"
                            :field-names="{
                              key: 'id',
                              title: 'name'
                            }"
                            :allow-search="false"
                            :allow-clear="false"
                            :data="groupTreeData"
                            dropdown-class-name="tree-select-scrollbar"
                            @change="filterUser()"
                          ></a-tree-select>
                        </a-form-item>
                      </a-col>
                      <a-col :span="6">
                        <a-space :size="18">
                          <a-button
                            v-permission="[Api.SYSTEM_USER_ADD]"
                            type="outline"
                            @click="showUserModal(0)"
                          >
                            <template #icon>
                              <icon-plus />
                            </template>
                            添加账号
                          </a-button>
                        </a-space>
                      </a-col>
                    </a-row>
                  </a-form>
                </a-col>
              </a-row>
            </template>
            <a-divider style="margin-top: 0" />
            <a-table
              :columns="tableColumns"
              :data="userList"
              stripe
              :pagination="false"
              :bordered="{
                cell: false,
                headerCell: true,
                wrapper: false
              }"
              :hoverable="false"
            >
              <template #status="{ record }">
                <a-switch
                  v-model="record.status"
                  :checked-value="1"
                  unchecked-color="#F53F3F"
                  :unchecked-value="0"
                  @change="handleModifyStatus($event as number, record.id)"
                >
                  <template #checked> 启 </template>
                  <template #unchecked> 关 </template>
                </a-switch>
              </template>
              <template #email="{ record }">
                {{ record.email || '-' }}
              </template>
              <template #operate="{ record }">
                <a-button
                  v-permission="[Api.SYSTEM_USER_GET_DOMAINS]"
                  type="primary"
                  class="c-btn-4"
                  title="设置区域"
                  @click="showGroupModal(record)"
                >
                  <template #icon>
                    <icon-relation />
                  </template>
                </a-button>
                <a-button
                  v-permission="[Api.SYSTEM_USER_GET_ROLES]"
                  type="primary"
                  title="设置角色"
                  @click="showRoleModal(record)"
                >
                  <template #icon>
                    <icon-user-group />
                  </template>
                </a-button>
                <a-button
                  v-permission="[Api.SYSTEM_USER_MODIFY]"
                  type="primary"
                  status="success"
                  title="设置信息"
                  @click="showUserModal(1, record)"
                >
                  <template #icon>
                    <icon-edit />
                  </template>
                </a-button>
                <a-button
                  v-permission="[Api.SYSTEM_USER_MODIFY]"
                  type="primary"
                  status="warning"
                  title="重置密码"
                  @click="showUserModal(2, record)"
                >
                  <template #icon>
                    <icon-refresh />
                  </template>
                </a-button>
                <a-button
                  v-permission="[Api.SYSTEM_USER_REMOVE]"
                  type="primary"
                  status="danger"
                  title="删除账号"
                  @click="handleRemoveUser(record)"
                >
                  <template #icon>
                    <icon-delete />
                  </template>
                </a-button>
              </template>
            </a-table>
            <Page :page="page" @change="pageChangehandle" />
          </a-card>
        </a-col>
      </a-row>
      <vModal
        v-model:visible="visibleUserModal"
        :title="modalTitle"
        @modal-handle-ok="userHandleOk"
        @modal-handle-cancel="userHandleCancel"
      >
        <div style="padding: 10px 15px">
          <a-form
            ref="userFormRef"
            :model="userForm"
            :auto-label-width="true"
            label-align="right"
          >
            <a-form-item
              v-if="modalType !== 2"
              field="mobile"
              label="手机"
              show-colon
              :rules="[
                {
                  required: true,
                  message: '手机号格式不正确',
                  match:
                    /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/
                }
              ]"
            >
              <a-input
                v-model="userForm.mobile"
                placeholder="请输入手机号"
                :disabled="modalType === 1"
              />
            </a-form-item>
            <a-form-item
              v-if="modalType === 0"
              field="groupId"
              label="分组"
              show-colon
              :rules="[
                {
                  required: true,
                  message: '分组不能未空'
                }
              ]"
            >
              <a-tree-select
                v-model="userForm.groupId"
                placeholder="请选择分组"
                :field-names="{
                  key: 'id',
                  title: 'name'
                }"
                :allow-search="false"
                :allow-clear="false"
                :data="groupTreeData"
                dropdown-class-name="tree-select-scrollbar"
              ></a-tree-select>
            </a-form-item>
            <a-form-item
              v-if="modalType !== 2"
              field="name"
              label="名称"
              show-colon
              :rules="[
                { required: true, message: '名称不能未空' },
                {
                  minLength: 2,
                  maxLength: 20,
                  message: '名称长度大于2个字节，且小于20个字节'
                }
              ]"
            >
              <a-input v-model="userForm.name" placeholder="请输入账号名称" />
            </a-form-item>
            <a-form-item
              v-if="modalType !== 1"
              field="pass"
              label="密码"
              show-colon
              :rules="[{ required: true, validator: validatePass }]"
            >
              <a-input-password
                v-model="userForm.pass"
                placeholder="请输入登录密码"
              />
            </a-form-item>
            <a-form-item
              v-if="modalType !== 1"
              field="checkPass"
              label="确认"
              show-colon
              :rules="[{ required: true, validator: validatePass2 }]"
            >
              <a-input-password
                v-model="userForm.checkPass"
                placeholder="再次确认密码"
              />
            </a-form-item>
            <a-form-item
              v-if="modalType !== 2"
              field="email"
              label="邮箱"
              show-colon
              :rules="[{ type: 'email', max: 200, message: '邮箱格式不正确' }]"
            >
              <a-input v-model="userForm.email" placeholder="请输入邮箱" />
            </a-form-item>
          </a-form>
        </div>
      </vModal>
      <vModal
        v-model:visible="visibleRoleModal"
        :title="modalTitle"
        @modal-handle-ok="roleHandleOk"
        @modal-handle-cancel="roleHandleCancel"
      >
        <a-transfer
          v-model="checkRoleList"
          :data="roleList"
          one-way
          :title="['权限设置', '权限已设置']"
        />
      </vModal>
      <vModal
        v-model:visible="visibleGroupModal"
        :title="modalTitle"
        @modal-handle-ok="groupHandleOk"
        @modal-handle-cancel="groupHandleCancel"
      >
        <div style="padding: 10px 15px">
          <a-tree
            v-if="groupTreeData.length"
            v-model:checked-keys="checkScopeList"
            :checkable="true"
            class="dtree"
            size="large"
            :field-names="{
              key: 'id',
              title: 'name'
            }"
            default-expand-all
            :data="groupTreeData"
            :block-node="true"
            :check-strictly="true"
          >
          </a-tree>
        </div>
      </vModal>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, nextTick, onMounted, h } from 'vue'
import { FormInstance } from '@arco-design/web-vue/es/form'
import { Modal, Message, TableColumnData } from '@arco-design/web-vue'
import {
  addUser,
  getUserList,
  modifyUser,
  removeUser,
  getUserRoles,
  setUserRoles,
  getUserGroupList,
  setUserGroup
} from '@/api/acs/user'
import vModal from '@/components/modal/index.vue'
import {
  UserListResParams,
  User,
  ModifyUserParams,
  UserRoleResParams,
  UserGroupResParams
} from '@/types/user'
import Page from '@/components/page/index.vue'
import { User as Api } from '@/enums/api'
import usePage, { IPage } from '@/components/page/index'
// import { format } from 'date-fns'
import { Md5 } from 'ts-md5'
import { getGroupTree, GroupTreeResParams, GroupTree } from '@/api/client'

export interface TransferItem {
  value: string
  label: string
  disabled: boolean
}
export interface Role extends TransferItem {
  id: string
  enabled: boolean
  name: string
}

const userFormRef = ref<FormInstance>()
const visibleUserModal = ref(false) // 是否显示用户对话框
const visibleRoleModal = ref(false) // 是否显示设置角色对话框
const visibleGroupModal = ref(false) // 是否显示设置分组范围对话框

const modalType = ref(0) // 对话框类型，0：添加，1：修改
const modalTitle = ref('') // 对话框标题
const groupTreeData = ref<GroupTree[]>([]) // 分组树

/**
 * 条件筛选表单
 */
const filterForm = reactive<{
  keyword?: string
  groupId?: number
}>({
  keyword: undefined,
  groupId: undefined
})

const userForm = reactive<{
  id: string
  status: number
  mobile: string
  groupId?: number
  name: string
  email?: string
  pass: string
  checkPass: string
}>({
  id: '',
  groupId: undefined,
  status: 1,
  name: '',
  email: '',
  mobile: '',
  pass: '',
  checkPass: ''
})

const validatePass = (value: any, callback: any) => {
  if (value === undefined || value.length <= 5) {
    callback('密码不能为空，且必须不能小于六位')
  } else {
    if (userForm.checkPass !== '') {
      if (!userFormRef.value) return
      userFormRef.value.validateField('checkPass', () => null)
    }
    callback()
  }
}
const validatePass2 = (value: any, callback: any) => {
  if (value === '') {
    callback('请再次输入密码')
  } else if (value !== userForm.pass) {
    callback('两次密码不匹配')
  } else {
    callback()
  }
}

const tableColumns: TableColumnData[] = [
  {
    title: '手机号',
    dataIndex: 'mobile',
    align: 'left',
    width: 125
  },
  {
    title: '用户名称',
    dataIndex: 'name',
    align: 'left',
    fixed: 'right',
    width: 95
  },
  {
    title: '所在区域',
    dataIndex: 'domain_name',
    align: 'left',
    width: 95,
    ellipsis: true,
    tooltip: true
  },
  {
    title: '邮箱号',
    dataIndex: 'email',
    align: 'center',
    slotName: 'email',
    width: 95,
    ellipsis: true,
    tooltip: true
  },
  {
    title: '注册时间',
    dataIndex: 'reg_time',
    width: 170,
    ellipsis: true,
    tooltip: true
  },
  {
    title: '最近活动时间',
    dataIndex: 'act_time',
    width: 170,
    ellipsis: true,
    tooltip: true
  },
  {
    title: '状态',
    dataIndex: 'status',
    slotName: 'status',
    width: 75,
    ellipsis: true,
    tooltip: true
  },
  {
    title: '操作',
    slotName: 'operate',
    align: 'left',
    fixed: 'right',
    width: 225
  }
]
const { page } = usePage()
const userList = ref<User[]>([]) // 用户列表
const roleList = ref<Role[]>([]) // 角色列表
const checkRoleList = ref<string[]>([]) // 已选中角色列表
const checkScopeList = ref<number[]>([]) // 已选中分组范围key
let defaultCheckScopeList: number[] = [] // 默认选中分组范围key

/**
 * 根据表单按条件筛选角色列表
 */
const filterUser = (): void => {
  getList().then(() => console.log('获取角色列表'))
}

/**
 * 分页变化事件
 * @param argPage
 */
const pageChangehandle = (argPage: IPage): void => {
  page.pageIndex = argPage.pageIndex
  page.pageSize = argPage.pageSize
  getList().then(() => console.log('获取住户列表'))
}

/**
 * 递归获取ng-tree需要的结构体
 * @param groups 接口返回的树状数组
 */
const getNodesTree = (groups: GroupTree): GroupTree => {
  groups.key = groups.id.toString()
  groups.title = groups.name
  if (groups.children && groups.children.length > 0) {
    groups.children.map(res => getNodesTree(res))
  }
  return groups
}

/**
 * 获取域树
 */
const getTree = async () => {
  try {
    const { tree }: GroupTreeResParams = await getGroupTree()
    groupTreeData.value = tree.map(groups => {
      return getNodesTree(groups)
    })
    if (groupTreeData.value.length > 0) {
      filterForm.groupId = groupTreeData.value[0].id
    }
  } catch (e) {
    console.error(e)
  }
}

/**
 * 获取用户列表
 */
const getList = async () => {
  try {
    const { groupId, keyword } = filterForm
    const { pageIndex, pageSize } = page
    const { users, total }: UserListResParams = await getUserList(
      groupId!,
      pageIndex,
      pageSize,
      keyword
    )
    page.total = total
    userList.value = users
  } catch (e) {
    console.error(e)
  }
}

/**
 * 隐藏role 对话框，重置表单
 */
const userHandleCancel = () => {
  userFormRef.value!.resetFields() // 初始化表单值
}

/**
 * 重置角色列表
 */
const roleHandleCancel = () => {
  roleList.value = []
  checkRoleList.value = []
}

/**
 * 重置权限范围列表
 */
const groupHandleCancel = () => {
  defaultCheckScopeList = []
  checkScopeList.value = []
}
/**
 * 显示角色modal
 * @param type modal 类型
 * @param user
 */
const showUserModal = (type: number, user?: User) => {
  // const isAdd = type === 0
  modalType.value = type
  if (type === 0) {
    modalTitle.value = `添加账号`
    visibleUserModal.value = true
    userForm.groupId = filterForm.groupId
  } else if (type === 1) {
    modalTitle.value = `修改 ${user!.name} 账号信息`
    const { id, name, mobile, email } = user!
    visibleUserModal.value = true
    nextTick(() => {
      userForm.id = id
      userForm.name = name
      userForm.mobile = mobile
      userForm.email = email
    })
  } else if (type === 2) {
    modalTitle.value = `重置 ${user!.name} 账号密码`
    const { id } = user!
    visibleUserModal.value = true
    nextTick(() => {
      userForm.id = id
    })
  }
}

/**
 * 显示设置角色对话框
 * @param user 修改时对应选中行数据
 */
const showRoleModal = async (user: User) => {
  try {
    const { id, name } = user
    modalTitle.value = `设置 ${name} 角色信息`
    const { roles }: UserRoleResParams = await getUserRoles(id)
    // roleList.value = roles
    roleList.value = roles.map(
      (item: { id: string; enabled: boolean; name: string }) => {
        if (item.enabled) {
          checkRoleList.value.push(item.id)
        }
        return {
          id: item.id,
          name: item.name,
          disabled: false,
          label: item.name,
          value: item.id,
          enabled: item.enabled
        }
      }
    )
    visibleRoleModal.value = true
    nextTick(() => {
      userForm.id = id
    })
  } catch (e) {
    console.error(e)
  }
}

/**
 * 显示设置分组树对话框
 * @param user 修改时对应选中行数据
 */
const showGroupModal = async (user: User) => {
  try {
    const { id, name } = user
    modalTitle.value = `设置 ${name} 权限范围`
    const { list }: UserGroupResParams = await getUserGroupList(id)
    checkScopeList.value = list.map(item => {
      return item.id
    })
    defaultCheckScopeList = checkScopeList.value
    visibleGroupModal.value = true
    nextTick(() => {
      userForm.id = id
    })
  } catch (e) {
    console.error(e)
  }
}

/**
 * 点击确认按钮时，cb(false)时不会继续后续操作
 * @param cb 回调函数，
 */
const userHandleOk = async (cb: (closed: boolean) => void) => {
  const isValid = await userFormRef.value?.validate()
  if (isValid) {
    return cb(false)
  }
  const { name, mobile, groupId, pass, email, status } = userForm
  try {
    if (modalType.value === 0) {
      const md5Pwd: any = Md5.hashStr(pass) // 密码按照md5加密传输
      await addUser(groupId!, name, md5Pwd, status, email, mobile)
      filterForm.groupId = groupId
      Message.success('添加成功')
      getList().then(() => console.log('获取用户列表'))
      // userList.value.unshift({
      //   id: mobile,
      //   name,
      //   status,
      //   email,
      //   mobile,
      //   reg_time: format(new Date(), 'yyyy-MM-dd HH:mm:ss')
      // })
    } else if (modalType.value === 1) {
      const users: ModifyUserParams = {
        user_id: userForm.id, // 用户ID
        name: userForm.name, // 名称
        email: userForm.email, // 邮箱
        mobile: userForm.mobile // 手机号
      }
      await modifyUser(users)
      const index = userList.value.findIndex(
        (item: { id: string }) => item.id === users.user_id
      )
      const item = userList.value[index]
      item.name = users.name!
      item.mobile = users.mobile!
      item.email = users.email
      Message.success('修改成功')
    } else if (modalType.value === 2) {
      const { pass, id } = userForm
      const md5Pwd: any = Md5.hashStr(pass) // 密码按照md5加密传输
      const users: ModifyUserParams = {
        user_id: id, // 用户ID
        pass: md5Pwd // 密码
      }
      await modifyUser(users)
      Message.success('重置成功')
    }
  } catch (e) {
    console.error(e)
  }
  return cb(true)
}

/**
 * 点击确认按钮时，cb(false)时不会继续后续操作
 * @param cb 回调函数，
 */
const roleHandleOk = async (cb: (closed: boolean) => void) => {
  const { id } = userForm
  const roles: Array<{ id: string; enabled: boolean }> = []
  try {
    roleList.value.map(
      (item: { id: string; value: string; enabled: boolean }) => {
        const isExist = checkRoleList.value.includes(item.id)
        if (item.enabled && !isExist) {
          roles.push({
            id: item.id,
            enabled: false
          })
        }
        if (!item.enabled && isExist) {
          roles.push({
            id: item.id,
            enabled: true
          })
        }
        return item
      }
    )
    if (roles.length <= 0) {
      Message.info('未选中角色，权限无改变')
      return cb(true)
    }
    await setUserRoles(id, roles)
    Message.success('权限设置成功')
  } catch (e) {
    console.error(e)
  }
  return cb(true)
}

/**
 * 点击确认按钮时，cb(false)时不会继续后续操作
 * @param cb 回调函数，
 */
const groupHandleOk = async (cb: (closed: boolean) => void) => {
  const scopeCheckedKeys = checkScopeList.value
  const scope: Array<{ id: number; enabled: boolean }> = []
  try {
    const scopList = defaultCheckScopeList
    ;[...new Set([...scopeCheckedKeys, ...scopList])].filter(item => {
      if (!scopeCheckedKeys.includes(item)) {
        scope.push({ id: item, enabled: false })
      }
      if (!scopList.includes(item)) {
        scope.push({ id: item, enabled: true })
      }
      return item
    })
    if (scope.length <= 0) {
      Message.info('权限范围未发生变化')
      return cb(true)
    }
    const { id } = userForm
    await setUserGroup(id, scope)
    Message.success('权限范围设置成功')
  } catch (e) {
    console.error(e)
  }
  return cb(true)
}

/**
 * 修改用户状态
 * @param val 状态值
 * @param userId
 */
const handleModifyStatus = async (val: number, userId: string) => {
  try {
    const users: ModifyUserParams = {
      user_id: userId, // 用户ID
      status: val
    }
    await modifyUser(users)
    const message = val === 1 ? '已开启' : '已锁定'
    Message.success(message)
  } catch (e) {
    setTimeout(() => {
      val = 1
    })
    // console.error(e)
  }
}

/**
 * 删除角色
 * @param role
 */
const handleRemoveUser = async (role: User) => {
  const { id, name } = role
  const title = {
    setup() {
      return () => h('strong', '警告')
    }
  }
  const ModalContent = {
    setup() {
      return () =>
        h('span', { style: 'margin-left: 10px;' }, [
          h('span', `确认删除 `),
          h('strong', `${name}`),
          h('span', ` 账号吗？`)
        ])
    }
  }
  Modal.warning({
    title: () => h(title),
    content: () => h(ModalContent),
    alignCenter: true,
    titleAlign: 'start',
    draggable: true,
    escToClose: true,
    width: 300,
    simple: true,
    hideCancel: false,
    onOk: async () => {
      try {
        await removeUser(id)
        const index = userList.value.findIndex(
          (item: { id: string }) => item.id === role.id
        )
        userList.value.splice(index, 1)
        Message.success('删除成功')
      } catch (e) {
        console.error(e)
      }
    }
  })
}

onMounted(async () => {
  try {
    await getTree().then(() => console.log('获取分组树列表'))
    getList().then(() => console.log('获取用户列表'))
  } catch (e) {
    console.log(e)
  }
})
</script>

<script lang="ts">
export default {
  name: 'User'
}
</script>

<style scoped lang="less">
.container {
  padding: 20px;
}
.dtree {
  padding: 0 10px;
  // max-height: 350px;
  :deep(.arco-tree-node-selected) {
    background-color: rgb(var(--gray-2));
  }
  :deep(.arco-tree-node:hover) {
    background-color: rgb(var(--gray-2));
  }
  :deep(.arco-tree-node-title:hover) {
    background-color: transparent;
  }
}

:deep(.arco-table-th) {
  &:last-child {
    .arco-table-th-item-title {
      margin-left: 16px;
    }
  }
}
</style>
