<script lang="ts" setup>
import {
  resetSpaceMatterPermit,
  getSpaceMemberList,
  addSpaceManager,
  updateSpaceMetterPermit,
} from '@/api/hr/people/share_ctrol'

import { ElDialog, ElMessageBox,ElStep,TreeInstance} from 'element-plus';
import { useOrgMemberStore } from "@/store/modules/orgMember";
import { dataTool } from 'echarts';
const props = withDefaults(defineProps<{
  uid:string,   //当前用户的uuid
  uuid:string,  //文档的uuid
  suid:string,  //空间的创建者
  spaceid:string, //空间uuid
  closeFunc:(refresh?:boolean)=>void,  //父级只需销毁组件
}>(),{})

const orgMembers = useOrgMemberStore()
const spacePermit=ref<{id:number,data:string,matterUid:string}>({}) //权限
const treeRef=ref<TreeInstance>() //tree组件的引用，为了实现初始选中状态
const managerMode=ref(false)
const managers=ref<string[]>([])
const firstLevelKeys = ref<string[]>([]) //默认展开的部门

let resultPermits: Record<string, number> = {};

interface Tree {
  id: string
  name:string
  superior?:string
  indeterminate?:boolean,
  radio?:number[];
  child?: Tree[]
  ismanager?:boolean,
  indeterminate2?:boolean,//for manager member
}

const dataSource = ref<Tree[]>([])

//权限组件保存
async function onSavePermChange(){
  resultPermits={}

  // 管理员设置
  if (managerMode.value){
    managers.value=[] //先清空
    dataSource.value.forEach(item=>{
      if(item.ismanager){
        managers.value.push("p0"+item.id)
      }
      
      if(item.child) collectManager(item)
    })

    await addSpaceManager(btoa(props.uid),{
      space:props.spaceid,
      mangers:managers.value.join("|")
    }).then(resp=>{
      console.log(resp)
    })
    props.closeFunc()
    return
  }

  dataSource.value.forEach(item=>{
    if(item.radio&&item.radio.length>0){
      if(item.indeterminate) {
        item.radio[0]+=10
      }
      resultPermits[item.id]=item.radio[0]
    }
    
    if(item.child) collectNodePermits(item)
  })

  spacePermit.value.data=JSON.stringify(resultPermits)

  updateSpaceMetterPermit(btoa(props.uid),{
    space:props.spaceid,
    matter:props.uuid,
    permits:spacePermit.value
  }).then(resp=>{
    console.log(resp)
  })
  props.closeFunc()
}

function collectManager(node:Tree){
  node.child?.forEach(ele => {
     if(ele.ismanager){
        managers.value.push("p0"+ele.id)
      }
      
      if(ele.child) collectManager(ele)
  });
}

//去遍历查找特殊设置的节点，并保存
function collectNodePermits(node:Tree){
  node.child?.forEach(ele => {
    if(ele.radio&&ele.radio.length>0){
       if(ele.indeterminate) {
        ele.radio[0]+=10
      }
      resultPermits[ele.id]=ele.radio[0]
    }
   
    if(ele.child){
      collectNodePermits(ele)
    }
  });
}


//递归修改子级元素
function onGroupValueChange(node:Tree, val:number[]){
  //if(node.indeterminate) node.indeterminate=false;
  updateChildNode(node, val)
  if(node.superior){
    updateParentNode(node)
  }
}

function updateChildNode(node:Tree, val:number[]){
  if(node.indeterminate) node.indeterminate=false;
  node.child?.forEach(ele => {
    ele.radio=val
    if(ele.child){
      updateChildNode(ele,val)
    }
  });
}

//递归更新父级
function updateParentNode(node:Tree){
  if(node.superior){
    
    const pnode = treeRef.value?.getNode(node.superior);
    if(pnode){
      const tdata=pnode.data as Tree 
      if (tdata.child?.every(ele=>{
        if(ele.indeterminate) return !ele.indeterminate;//注意这里有个取反计算

        if(ele.radio?.length==0) return ele.radio.length==tdata.radio?.length;
        return ele.radio?.length==tdata.radio?.length && ele.radio[0]==tdata.radio[0]
      })) {
        tdata.indeterminate=false
      }else{
        tdata.indeterminate=true
      }

      updateParentNode(tdata)
    }
    
  }
}


//重置当前文档权限
function delMatterPermit(matter_uuid:string){
  resetSpaceMatterPermit(btoa(props.uid),{
    space:props.spaceid,
    matter:matter_uuid,
  }).then(()=>{
    refreshSpaceData()
  })
}

function onShowManagers(){
  managers.value.forEach(item=>{
    const node = treeRef.value?.getNode(item.replace("p0",""));
    if(node && node.data){
        node.data.ismanager=true
        setParentIndeterminate(node.data as Tree)
    }
  })
}

function setParentIndeterminate(node:Tree){
  if(node.superior){
    const pnode = treeRef.value?.getNode(node.superior);
    if(pnode){
      const tdata=pnode.data as Tree 
      tdata.indeterminate2=true

      setParentIndeterminate(tdata)
    }
  }
}

function refreshSpaceData(){
    getSpaceMemberList(
      btoa(props.uid),
      {space:props.spaceid,matter:props.uuid}
    ).then(resp=>{
      resp.data?.dprts?.forEach(item=>{    
        for(let data of dataSource.value){
          if (data.id==item) return;
          if (checkNode(item,data)) return;
        }
  
        addNode(item,orgMembers.dataTree)
      });

      if(dataSource.value.length>0){//只添加第一个最顶级部门
        firstLevelKeys.value.push(dataSource.value[0].id)
      }

      resp.data?.members?.forEach(item=>{
        const mid=item.replace("p0","")
        for(let data of dataSource.value){
          if(checkNode(mid,data)) return;
        }
         
        dataSource.value.push({id:mid,name:orgMembers.listMap[mid],radio:[]})
      });

      managers.value=resp.data?.managers.split("|")
      spacePermit.value.id=resp.data?.permits.ID
      spacePermit.value.matterUid=resp.data?.permits.MatterUuid
      spacePermit.value.data=resp.data.permits.data!="" ? resp.data.permits.data : "{}"

      nextTick(() => {
        const permitJson = JSON.parse(spacePermit.value.data) //object
        Object.keys(permitJson).forEach(key=>{
          const node = treeRef.value?.getNode(key);
          if(node && node.data){
            if(permitJson[key]>10){
              node.data.radio = [permitJson[key]%10]
              node.data.indeterminate=true  
            }else{
              node.data.radio = [permitJson[key]]
            }
          }
        })
      });
      
  })
}

function addNode(key:string,node:Tree){
  node.child?.forEach(ele => {
    if(ele.id==key){
      const eleClone=structuredClone(toRaw(ele)) //这里ele是Proxy，无法clone，所以要toRaw拿到原始object
      //eleClone.radio=[2]
      eleClone.superior=ele.superior
      dataSource.value.push(eleClone) //{id:ele.id,name:ele.name,radio:2,stage:level,children:ele.children}
      return
    }
    if(ele.child){
      addNode(key,ele)
    }
  });
}

function checkNode(key:string,node:Tree):boolean{
  for (const ch of node.child||[]) {
    if(ch.id==key){
      return true
    }
    if(ch.child){
      //这里不能直接return，因为return后，就中断了for循环，但是true的情况下可以直接return
      if(checkNode(key,ch)) return true; 
    }
  }

  return false;
}


onMounted(()=>{
  refreshSpaceData()
})

</script>

<template>
  <el-dialog :model-value="true" :style="{'max-height': '750px'}" v-on:close="closeFunc()">
    <template #header>
      <el-button link :class="managerMode ? '' :'moveon'" @click="managerMode=false;" >文档权限管理</el-button>
      <el-button v-if="spacePermit.matterUid==spaceid&&uid==suid" :class="managerMode ? 'moveon' :''" link @click="managerMode=true; onShowManagers()">管理员管理</el-button>
    </template>
   
    <div v-if="uuid==spacePermit.matterUid&&uuid!=spaceid" class="tips">当前文档存在定制权限，与空间权限不一致。<el-button size="small" @click="delMatterPermit(uuid)">恢复</el-button></div>
    <div class="tree-node" style="width:93%;font-weight: bold;position: sticky;">
      <span style="width: 200px;text-align: center;">名称</span>
      <div v-if="managerMode" class="buttons">
        <span>管理员</span>
      </div>
      <div v-else class="buttons">
        <el-tooltip placement="top" effect="dark" 
          content="禁止访问">
          <span>不可见</span>
        </el-tooltip>
        <el-tooltip placement="top" effect="dark" 
          content="仅可预览，不可下载">
          <span>仅预览</span>
        </el-tooltip>
        <el-tooltip placement="top" effect="dark" 
          content="可下载可见文件，不可上传文件">
          <span>可下载</span>
        </el-tooltip>
        <el-tooltip placement="top" effect="dark" 
          content="可上传和下载可见文件">
          <span>上传下载</span>
        </el-tooltip>
        <el-tooltip placement="top" effect="dark" 
          content="可上传、下载、编辑文档">
          <span>编辑</span>
        </el-tooltip>
      </div>
    </div>
    <div class="tablelist">
      <el-tree
          ref="treeRef"
          :data="dataSource"
          node-key="id"
          accordion
          :props="{label: 'name',children:'child'}"
          :default-expanded-keys="firstLevelKeys"
          :expand-on-click-node="false"	
        >
        <template #default="{ node, data }">
          <div class="tree-node">
            <span>{{ data.name }}</span>
            
            <div v-if="managerMode" class="buttons">
              <el-checkbox  v-model="data.ismanager" :indeterminate="data.indeterminate2" />
            </div>
            <div  v-else class="buttons"> 
              <el-checkbox-group :min="0" :max="1"  v-model="data.radio" @change="(val)=>onGroupValueChange(data,val)">
                <el-checkbox key="forbid"  :indeterminate="data.indeterminate" :value="0" />
                <el-checkbox key="view" :indeterminate="data.indeterminate" :value="1" />
                <el-checkbox key="download" :indeterminate="data.indeterminate" :value="2" />
                <el-checkbox key="updown" :indeterminate="data.indeterminate" :value="3" />
                <el-checkbox key="edit" :indeterminate="data.indeterminate" :value="4" />
              </el-checkbox-group>
            </div>
          </div>
        </template>
      </el-tree>
    </div>
    
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="closeFunc()">取消</el-button>
        <el-button type="primary" @click="onSavePermChange">保存</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
  .tablelist{
    width: 94%;
    height: 565px;
    overflow-y: scroll
  }
  .tips{
    display: flex;
    align-items: center;
    margin: 5px;
    padding: 5px 32px;
    background-color: #d7d1ca;
  }
  .tree-node{
    display: flex;
    flex-direction: row;
    width: 100%;
    align-items: center;
    .buttons{
      margin: 0 50px 0 auto;
      span{
        width: 26px;
        margin: 0 7px;
      }
    }
  }
  .el-checkbox{
    width: 26px;
  }
  .moveon{
    background-color: rgb(109, 187, 238);
  }
  .el-tree{
    /* 让整个弹出窗口位置更高一些*/
    --el-tree-node-content-height:33px; 
  }
</style>
