<!--
 * auth.vue
 * Copyright (C) 2024 veypi <i@veypi.com>
 * 2024-06-12 18:38
 * Distributed under terms of the MIT license.
 -->
<template>
  <div class="">
    <div class="flex justify-between">
      <div class="text-3xl">角色管理</div>
      <div @click="created(0)">创建角色</div>
    </div>
    <div class="w-full">
      <crud vertical :keys="role_keys" :data="role" @update="update($event, role, api.app.RolePatch, app.id)">
        <template #k_created_at="{ value }">{{ util.datetostr(value) }}</template>
        <template #k__="{ row }">
          <div color="primary" size="sm" @click="show_dialog(0,
            row.id)">权限</div>
          <div color="secondary" size="sm" @click="show_dialog(1,
            row.id)">用户</div>
          <div color="negative" size="sm" @click="del(0, row.id)">删除</div>
          <template v-if="row.id === app.init_role_id">
            <div color="positive" disable size="sm">初始角色</div>
          </template>
          <template v-else>
            <div size="sm" @click="api.app.Patch(app.id, {
              init_role_id:
                row.id
            }).then(_ => app.init_role_id = row.id)">设置为初始角色</div>
          </template>
        </template>
      </crud>
    </div>

    <div class="flex mt-16 justify-between">
      <div class="text-3xl">资源管理</div>
      <div @click="created(1)">创建资源</div>
    </div>
    <div class="w-full">
      <crud vertical :keys="resource_keys" :data="resource"
        @update="update($event, resource, api.app.ResourcePatch, app.id)">
        <template #k_created_at="{ value }">{{ util.datetostr(value) }}</template>
        <template #k__="{ row }">
          <div color="negative" size="sm" @click="del(1, row.name)">删除</div>
        </template>
      </crud>
    </div>

    <UModal v-model="dialog" :ui="{ 'width': '' }">
      <UCard v-if="dialog_obj" style="width: 1000px;max-width: 90vw;">
        <template #header>
          <div class="items-center flex">
            <div class="text-2xl">{{ dialog_obj.name }}
            </div>
            <div class="flex-grow"></div>
            <div v-if="dialog_mode">
              <vinput :model-value="''" type="select" :options="['1', '2']" select-none="添加用户"></vinput>
              <!-- <USelect filled :model-value="''" @update:model-value="roleuser.add" use-input hide-selected fill-input -->
              <!--   input-debounce="0" label="添加用户" :options="users_cache" @filter="filterFn" style="width: 20rem"> -->
              <!-- </USelect> -->
            </div>
            <div v-else @click="created(2, { role_id: dialog_obj.id })">添加权限</div>
          </div>
        </template>

        <div v-if="dialog_mode">
          <crud vertical :keys="users_keys" :data="users">
            <template #k__="{ row }">
              <div color="negative" size="sm" @click="roleuser.drop(row)">删除</div>
            </template>
          </crud>
        </div>
        <div v-else>
          <crud vertical :keys="access_keys" :data="access" @update="update($event, access, api.access.Patch)">
            <template #k__="{ row }">
              <div color="negative" size="sm" @click="del(2, row.id)">删除</div>
            </template>
          </crud>
        </div>

      </UCard>
    </UModal>
  </div>
</template>

<script lang="ts" setup>
import type { models } from '#imports';
import msg from '@veypi/msg';

let dialog = ref(false)
let dialog_mode = ref(0)
let dialog_obj = ref<models.Role>({} as any)
const role_keys = ref<any>([
  {
    name: 'id',
    label: 'ID',
  },
  { name: 'name', label: '标识符' },
  { name: 'des', label: '描述', editable: true },
  { name: 'created_at', label: '创建时间' },
  { name: 'user_count', label: '绑定用户数' },
  {
    name: '_', label: '操作', style: { 'justify-content': 'start' },
    width: 40
  },
])
const resource_keys = ref<any>([
  { name: 'name', label: '标识符' },
  { name: 'des', label: '描述', editable: true },
  { name: 'created_at', label: '创建时间' },
  {
    name: '_', label: '操作', style: { 'justify-content': 'start' },
    width: 40
  },
])
const access_keys = ref<any>([
  { name: 'id', label: 'ID' },
  { name: 'name', label: '标识符' },
  { name: 'rid', label: '特定子资源id', editable: true },
  {
    name: 'level', label: '权限等级', editable: true, typ:
      ArgType.Select, options: LevelOptions,
  },
  {
    name: '_', label: '操作', style: { 'justify-content': 'start' },
    width: 40
  },
])
const users_keys = ref<any>([
  { name: 'id', label: 'ID' },
  { name: 'username', label: '用户名' },
  { name: 'nickname', label: '昵称' },
  {
    name: '_', label: '操作', style: { 'justify-content': 'start' },
    width: 40
  },
])

let access = ref<models.Access[]>([])
let users = ref<models.UserRole[]>([])
let users_cache = ref<any[]>([])
const resource = ref<any[]>([])
const role = ref<any[]>([])
const app = inject('app') as Ref<models.App>

watch(computed(() => app.value.id), (v) => {
  sync(v)

})

const sync = (id: any) => {
  if (!id) {
    return
  }
  api.app.RoleList(id, {}).then(e => {
    role.value = e
  })
  api.app.ResourceList(id).then(e => {
    resource.value = e
  })
}

const show_dialog = (mode: number, idx: string) => {
  dialog_obj.value = role.value.find(e => e.id === idx)
  dialog.value = true
  dialog_mode.value = mode
  if (mode) {
    api.user.UserRoleList('-', { role_id: idx }).then(e => {
      console.log(e)
      users.value = e
    })
  } else {
    api.access.List({ app_id: app.value.id, role_id: idx }).then(e => {
      access.value = e
    })
  }
}

// 0: role 1: resource 2: access 3: users
const crud_option = (mode: number) => {
  let res = {
    api: api.app.RolePatch(app.value.id),
    lable: '角色',
    obj: role,
  }
  if (mode === 1) {
    res.api = api.resource(app.value.id) as any
    res.lable = '资源'
    res.obj = resource
  } else if (mode === 2) {
    res.api = api.access(app.value.id) as any
    res.lable = '权限'
    res.obj = access
  } else if (mode === 3) {
    res.api = api.user as any
    res.lable = '用户'
    res.obj = users
  }
  return res
}
const created = (k: number, props?: any) => {
  let opt = crud_option(k)
  let options;
  let prompt;
  if (k !== 2) {
    prompt = { model: '', type: 'text' }
  } else {
    console.log(k)
    options = {
      model: '', type: 'radio', items: resource.value.map(e => {
        return {
          label: e.name,
          value: e.name
        }
      })
    }
  }
  // $q.dialog({
  //   title: '创建' + opt.lable,
  //   message: '请输入标识码',
  //   prompt: prompt as any,
  //   options: options as any,
  //   cancel: true,
  //   persistent: true
  // }).onOk(data => {
  //   opt.api.create(data, props).then(e => {
  //     msg.Info('创建成功')
  //     opt.obj.value.push(e)
  //   }).catch(e => {
  //     msg.Warn('创建失败： ' + e)
  //   })
  // })
}

const update = (props: any[], objs: any, cb: any, topid?: string) => {
  // let opt = crud_option(k)
  let patch = cb
  if (topid) {
    patch = (id: string, props: any) => {
      return cb(topid, id, props)
    }
  }
  for (let i in props) {
    let id = objs[i].id
    patch(id, props[i]).then(() => {
      Object.assign(objs[i], props[i])
    }).catch((e: any) => {
      msg.Warn('更新失败： ' + e)
    })
  }
}

const del = (k: number, id: string) => {
  let opt = crud_option(k)
  $q.dialog({
    title: '是否确定删除',
    message: '',
    cancel: true,
    persistent: true
  }).onOk(() => {
    opt.api.del(id).then(e => {
      msg.Info('删除成功')
      opt.obj.value.splice(opt.obj.value.findIndex(e => e.name === id
        || e.id === id), 1)
    }).catch(e => {
      msg.Warn('删除失败： ' + e)
    })
  })
}

const roleuser = {
  add: (u: any) => {
    let idx = users.value.findIndex(e => e.id == u.id)
    if (idx >= 0) {
      return
    }
    api.role(app.value.id).add(dialog_obj.value?.id || '', u.id).then(e => {
      users.value.push(u)
      dialog_obj.value.user_count = dialog_obj.value?.user_count + 1
    })
  },
  drop: (u: any) => {
    api.role(app.value.id).drop(dialog_obj.value?.id || '', u.id).then(e => {
      users.value.splice(users.value.findIndex(e => e.id === u.id), 1)
      dialog_obj.value.user_count = dialog_obj.value?.user_count - 1
    })
  }
}

const filterFn = (val: string, cb: any) => {
  if (val && val.length > 1) {
    api.user.list({ name: val }).then((e: modelsUser[]) => {
      cb(() => {
        users_cache.value = e.map(i => {
          return Object.assign({
            name: i.username,
            value: i.id,
          }, i)
        })
      })
    })
  }
}
onMounted(() => {
  sync(app.value.id)
})
</script>

<style scoped></style>
