<template>
  <el-dialog
      v-model="showDialog"
      :title="popTitle"
      width="500px"
      :destroy-on-close="true"
  >
    <el-form
        :model="formData"
        label-width="90px"
        ref="formRef"
        :rules="formRules"
        class="page-form"
        v-loading="loading"
    >
      <el-form-item :label="t('roleName')" prop="role_name">
        <el-input
            v-model.trim="formData.role_name"
            :placeholder="t('roleNamePlaceholder')"
            clearable
            :disabled="formData.uid"
            class="input-width"
            maxlength="10"
            :show-word-limit="true"
        />
      </el-form-item>


      <el-form-item label="类型">
        <el-radio-group v-model="formData.role_key">
        <span v-for="(item,index) in roleKeyList" class="mr-2">
          <el-radio :label="item.value">{{ item.name }}</el-radio>
        </span>
        </el-radio-group>
      </el-form-item>


      <el-form-item :label="t('status')">
        <el-radio-group v-model="formData.status">
          <el-radio :label="1">{{ t('startUsing') }}</el-radio>
          <el-radio :label="0">{{ t('statusDeactivate') }}</el-radio>
        </el-radio-group>
      </el-form-item>
	  
	  
	  
	  <el-form-item label="部门" >
	    <el-select
	      class="input-width"
	      v-model="formData.dept_id"
	      clearable
	      placeholder="请选择部门"
	    >
	      <el-option label="请选择" value=""></el-option>
	      <el-option
	        v-for="(item, index) in parentDepartmentIdList"
	        :key="index"
	        :label="item['department_name']"
	        :value="item['id']"
	      />
	    </el-select>
	  </el-form-item>

      <el-form-item :label="t('permission')" prop="rules">
        <el-tabs v-model="activePermissionTab" class="w-full">
          <!-- PC端权限 -->
          <el-tab-pane label="PC端权限" name="pc">
            <div class="flex items-center justify-between w-11/12">
              <div>
                <el-checkbox v-model="selectAllPC" :label="t('selectAll')"/>
                <el-checkbox v-model="checkStrictlyPC" :label="t('checkStrictly')"/>
              </div>
              <el-button link type="primary" @click="menuActionPC()">{{
                  t('foldText')
                }}
              </el-button>
            </div>
            <el-scrollbar height="35vh" class="w-full">
              <el-tree
                  :data="menus"
                  :props="{ label: 'menu_name' }"
                  :default-checked-keys="formData.rules"
                  :check-strictly="checkStrictlyPC"
                  show-checkbox
                  default-expand-all
                  @check-change="handleCheckChangePC"
                  node-key="menu_key"
                  ref="treeRefPC"
              />
            </el-scrollbar>
          </el-tab-pane>
          
          <!-- 移动端权限 -->
          <el-tab-pane label="移动端权限" name="mobile">
            <div class="flex items-center justify-between w-11/12">
              <div>
                <el-checkbox v-model="selectAllMobile" :label="t('selectAll')"/>
                <el-checkbox v-model="checkStrictlyMobile" :label="t('checkStrictly')"/>
              </div>
              <el-button link type="primary" @click="menuActionMobile()">{{
                  t('foldText')
                }}
              </el-button>
            </div>
            <el-scrollbar height="35vh" class="w-full">
              <el-tree
                  :data="mobileMenus"
                  :props="{ label: 'menu_name' }"
                  :default-checked-keys="formData.mobile_rules"
                  :check-strictly="checkStrictlyMobile"
                  show-checkbox
                  default-expand-all
                  @check-change="handleCheckChangeMobile"
                  node-key="menu_key"
                  ref="treeRefMobile"
              />
            </el-scrollbar>
          </el-tab-pane>
        </el-tabs>
      </el-form-item>
    </el-form>

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
        <el-button
            type="primary"
            :loading="loading"
            @click="confirm(formRef)"
        >{{ t('confirm') }}</el-button
        >
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup async>
import {ref, reactive, computed, watch, toRaw} from 'vue'
import {t} from '@/lang'
import {
  getWithDepartmentsList} from '@/app/api/departments'
import type {FormInstance} from 'element-plus'
import {addRole, editRole, getRoleInfo} from '@/app/api/sys'
import {getAuthMenus, getUniappMenus, getRoleUniappMenus, setRoleUniappMenus} from '@/app/api/auth'
import {useDictionary} from '@/app/api/dict'
import {debounce} from '@/utils/common'

const showDialog = ref(false)
const loading = ref(false)
const isOpen = ref(true)

let popTitle: string = ''

// 获取权限数据
const menus = ref<Record<string, any>[]>([])
const mobileMenus = ref<Record<string, any>[]>([])

// 获取PC端菜单
getAuthMenus({is_button: 0}).then((res) => {
  menus.value = res.data
})

// 获取移动端菜单（UniApp菜单权限）
const getMobileMenus = async () => {
  try {
    const res = await getUniappMenus()
    if (res.data) {
      mobileMenus.value = res.data.map(item => ({
        menu_key: item.menu_key,
        menu_name: item.menu_name,
        id: item.id,
        children: []
      }))
    }
  } catch (error) {
    console.error('获取移动端菜单失败:', error)
    // 如果获取失败，设置一个空数组
    mobileMenus.value = []
  }
}
getMobileMenus()

// 当前活动的权限标签页
const activePermissionTab = ref('pc')

// PC端权限相关
const selectAllPC = ref(false)
const checkStrictlyPC = ref(false)
const treeRefPC: Record<string, any> | null = ref(null)
watch(selectAllPC, () => {
  if (treeRefPC.value) {
    if (selectAllPC.value) {
      treeRefPC.value.setCheckedNodes(toRaw(menus.value))
    } else {
      treeRefPC.value.setCheckedNodes([])
    }
  }
})

// 移动端权限相关
const selectAllMobile = ref(false)
const checkStrictlyMobile = ref(false)
const treeRefMobile: Record<string, any> | null = ref(null)
watch(selectAllMobile, () => {
  if (treeRefMobile.value) {
    if (selectAllMobile.value) {
      treeRefMobile.value.setCheckedNodes(toRaw(mobileMenus.value))
    } else {
      treeRefMobile.value.setCheckedNodes([])
    }
  }
})

const parentDepartmentIdList = ref([] as any[])
const setParentDepartmentIdList = async () => {
  parentDepartmentIdList.value = await (await getWithDepartmentsList({})).data
}
setParentDepartmentIdList()

const roleKeyList = ref([])
const getRolekeyDictList = async () => {
  roleKeyList.value = await (
      await useDictionary('role_key')
  ).data.dictionary
}
getRolekeyDictList()

// PC端权限处理函数
const handleCheckChangePC = debounce((e) => {
  if (treeRefPC.value) {
    formData.rules = treeRefPC.value.getCheckedKeys()
  }
})

const menuActionPC = () => {
  if (isOpen.value) {
    collapseAllPC(menus.value)
    isOpen.value = false
  } else {
    unFoldAllPC(menus.value)
    isOpen.value = true
  }
}

// 移动端权限处理函数
const handleCheckChangeMobile = debounce((e) => {
  if (treeRefMobile.value) {
    formData.mobile_rules = treeRefMobile.value.getCheckedKeys()
  }
})

const menuActionMobile = () => {
  if (isOpen.value) {
    collapseAllMobile(mobileMenus.value)
    isOpen.value = false
  } else {
    unFoldAllMobile(mobileMenus.value)
    isOpen.value = true
  }
}

// PC端全部展开
const unFoldAllPC = (data: any) => {
  if (treeRefPC.value && treeRefPC.value.store) {
    Object.keys(data).forEach((key: string | any) => {
      if (treeRefPC.value.store.nodesMap[data[key].menu_key]) {
        treeRefPC.value.store.nodesMap[data[key].menu_key].expanded = true
      }
      if (data[key].children && data[key].children.length > 0)
        unFoldAllPC(data[key].children)
    })
  }
}
// PC端全部折叠
const collapseAllPC = (data: any) => {
  if (treeRefPC.value && treeRefPC.value.store) {
    Object.keys(data).forEach((key: string | any) => {
      if (treeRefPC.value.store.nodesMap[data[key].menu_key]) {
        treeRefPC.value.store.nodesMap[data[key].menu_key].expanded = false
      }
      if (data[key].children && data[key].children.length > 0)
        collapseAllPC(data[key].children)
    })
  }
}

// 移动端全部展开
const unFoldAllMobile = (data: any) => {
  if (treeRefMobile.value && treeRefMobile.value.store) {
    Object.keys(data).forEach((key: string | any) => {
      if (treeRefMobile.value.store.nodesMap[data[key].menu_key]) {
        treeRefMobile.value.store.nodesMap[data[key].menu_key].expanded = true
      }
      if (data[key].children && data[key].children.length > 0)
        unFoldAllMobile(data[key].children)
    })
  }
}
// 移动端全部折叠
const collapseAllMobile = (data: any) => {
  if (treeRefMobile.value && treeRefMobile.value.store) {
    Object.keys(data).forEach((key: string | any) => {
      if (treeRefMobile.value.store.nodesMap[data[key].menu_key]) {
        treeRefMobile.value.store.nodesMap[data[key].menu_key].expanded = false
      }
      if (data[key].children && data[key].children.length > 0)
        collapseAllMobile(data[key].children)
    })
  }
}
/**
 * 表单数据
 */
const initialFormData = {
  role_id: 0,
  role_name: '',
  status: 1,
  role_key: '',
  dept_id:'',
  rules: [],
  mobile_rules: [], // 新增移动端权限字段
}
const formData: Record<string, any> = reactive({...initialFormData})

const formRef = ref<FormInstance>()

// 表单验证规则
const formRules = computed(() => {
  return {
    role_name: [
      {required: true, message: t('roleNamePlaceholder'), trigger: 'blur'},
    ],
    rules: [
      {
        validator: (rule: any, value: string, callback: any) => {
          if (!value.length) callback(new Error(t('rulesPlaceholder')))
          else callback()
        },
        trigger: 'blur',
      },
    ],
  }
})

const emit = defineEmits(['complete'])

/**
 * 确认
 * @param formEl
 */
const confirm = async (formEl: FormInstance | undefined) => {
  if (loading.value || !formEl) return
  const save = formData.role_id ? editRole : addRole

  await formEl.validate(async (valid) => {
    if (valid) {
      loading.value = true

      const data = Object.assign({}, formData)
      
      // PC端权限处理
      if (treeRefPC.value) {
        data.rules = data.rules.concat(treeRefPC.value.getHalfCheckedKeys())
      }
      
      // 移动端权限处理
      if (treeRefMobile.value) {
        data.mobile_rules = data.mobile_rules.concat(treeRefMobile.value.getHalfCheckedKeys())
        
        // 调用UniApp权限设置API
        if (data.role_id && data.mobile_rules.length >= 0) {
          try {
            await setRoleUniappMenus(data.role_id, data.mobile_rules)
          } catch (error) {
            console.error('设置移动端权限失败:', error)
          }
        }
      }

      save(data)
          .then((res) => {
            loading.value = false
            showDialog.value = false

            emit('complete')
          })
          .catch(() => {
            loading.value = false
            // showDialog.value = false
          })
    }
  })
}

const setFormData = async (row: any = null) => {
  loading.value = true
  selectAllPC.value = false
  selectAllMobile.value = false
  Object.assign(formData, initialFormData)
  popTitle = t('addRole')
  if (row) {
    popTitle = t('updateRole')
    const data = await (await getRoleInfo(row.role_id)).data
    
    // 获取移动端权限数据
    let mobileRulesData = []
    try {
      const mobileRes = await getRoleUniappMenus(row.role_id)
      if (mobileRes.data) {
        mobileRulesData = mobileRes.data.map(item => item.menu_key)
      }
    } catch (error) {
      console.error('获取移动端权限失败:', error)
    }
    
    Object.keys(formData).forEach((key: string) => {
      if (data[key] != undefined) {
        if (key == 'rules') {
          const arr = data.rules
          const newArr: any = []

          Object.keys(data.rules).forEach((i) => {
            checked(data.rules[i], menus.value, newArr)
          })
          formData[key] = newArr
        } else if (key == 'mobile_rules') {
          formData[key] = mobileRulesData
        } else {
          formData[key] = data[key]
        }
      }
    })
    
    // 设置移动端权限数据
    formData.mobile_rules = mobileRulesData
  }
  loading.value = false
}

function checked(menuKey: string, data: any, newArr: any) {
  Object.keys(data).forEach((key: string) => {
    const item = data[key]
    if (item.menu_key == menuKey) {
      if (!item.children || item.children.length == 0) {
        newArr.push(item.menu_key)
      }
    } else {
      if (item.children && item.children.length > 0) {
        checked(menuKey, item.children, newArr)
      }
    }
  })
}

defineExpose({
  showDialog,
  setFormData,
})
</script>

<style lang="scss" scoped></style>
