<template>
  <div class="data-form">
    <IxForm :control="formGroup"
        :control-col="{span:18}"
        :label-col="{span:6}"
        label-align="end"
        layout="horizontal"
        message-tooltip>
      <IxDivider dashed labelPlacement="start">基本信息</IxDivider>
      <IxRow>
        <IxCol :span="6">
          <IxFormItem :gutter="[0, 10]" label="头像">
            <IxUpload
                v-model:files="files"
                :action="uploadBaseUrl"
                :max-count="1"
                :progress="{
      strokeColor: {
        '0%': '#108EE9',
        '100%': '#87D068',
      },
      strokeWidth: 3,
    }"
                :request-data="requestData">
              <template #list>
                <IxUploadFiles :icon="{file: 'paper-clip', remove: 'close', retry: 'redo'}" type="imageCard"/>
              </template>
            </IxUpload>
          </IxFormItem>
        </IxCol>
        <IxCol :span="18">
          <IxRow>
            <IxCol :span="8">
              <IxFormItem :gutter="[0,10]" label="用户昵称">
                <IxInput control="nickname"/>
              </IxFormItem>
            </IxCol>
          </IxRow>
          <IxRow>
            <IxCol :span="8">
              <IxFormItem
                  :gutter="[0, 10]"
                  label="性别">
                <IxSelect :dataSource="genderDataSource" control="gender"/>
              </IxFormItem>
            </IxCol>
          </IxRow>
          <IxRow>
            <IxCol :span="8">
              <IxFormItem :gutter="[0, 10]" label="所属单位">
                <IxSelect
                    :data-source="tenantList"
                    control="tenantId"
                    get-key="id" label-key="tenantName"/>
              </IxFormItem>
            </IxCol>
          </IxRow>
        </IxCol>
      </IxRow>
      <IxDivider dashed labelPlacement="start">账号信息</IxDivider>
      <IxFormWrapper control="account">
        <IxRow>
          <IxCol :span="6">
            <IxFormItem :gutter="[0,10]" label="用户名">
              <IxInput control="username"/>
            </IxFormItem>
          </IxCol>
          <IxCol :span="6">
            <IxFormItem
                :gutter="[0, 10]"
                label="手机号">
              <IxInput :min="0" control="phone"/>
            </IxFormItem>
          </IxCol>
          <IxCol :span="6">
            <IxFormItem :gutter="[0,10]" label="邮箱">
              <IxInput control="email"/>
            </IxFormItem>
          </IxCol>
          <IxCol :span="6">
            <IxFormItem :gutter="[0,10]" label="密码">
              <IxInput control="secret" type="password"/>
            </IxFormItem>
          </IxCol>
        </IxRow>
      </IxFormWrapper>
    </IxForm>
    <IxDivider dashed labelPlacement="start">角色信息</IxDivider>
    <IxForm :control="searchForm" :control-col="{span:18}" :label-col="{span:6}"
        label-align="end"
        layout="horizontal"
        @submit.prevent="searchHandler">
      <IxRow>
        <IxCol :span="6">
          <IxFormItem :gutter="[0, 10]" align="center" label="角色编码">
            <IxInput clearable control="roleCode" placeholder="请输入角色编码"/>
          </IxFormItem>
        </IxCol>
        <IxCol :span="6">
          <IxFormItem :gutter="[0, 10]" label="角色名称">
            <IxInput clearable control="roleName" placeholder="请输入角色名称"/>
          </IxFormItem>
        </IxCol>
        <IxCol :span="6">
          <IxFormItem :gutter="[0, 10]" label=" ">
            <IxButton icon="search" type="submit">搜索</IxButton>
          </IxFormItem>
        </IxCol>
      </IxRow>
    </IxForm>
    <IxTable
        v-model:selectedRowKeys="selectedRowKeys"
        :columns="columns"
        :dataSource="datasource"
        :pagination="false"
        :scroll="{height:'30rem'}"
        :spin="tableSpin"
        cascader-strategy="off"
        class="list-table">
    </IxTable>
    <IxRow justify="end">
      <IxPagination v-model:pageIndex="pagination.current" v-model:pageSize="pagination.size" :total="pagination.total"
          class="pagination"
          show-quick-jumper
          show-size-changer show-total @change="pagingChangeHandler"/>
    </IxRow>
  </div>
</template>

<script lang="ts" setup>
import {
  useFormGroup,
  Validators
} from '@idux/cdk'
import { SelectData } from '@idux/components/select/src/types'
import { ref } from 'vue'
import { TreeSelectNode } from '@idux/components/tree-select/src/types'
import { VKey } from '@idux/cdk/utils'
import { TableColumn } from '@idux/components/table'
import RoleApi from '@/pages/sys/role/role-api.ts'
import Utils from '@/common/utils'
import { Gender } from '@/pages/sys/user/constants.ts'
import TenantApi from '@/pages/sys/tenant/tenant-api.ts'
import { uploadBaseUrl } from '@/common'
import { UploadFile } from '@idux/components'
import AppApi from '@/common/app/app-api.ts'

const props = withDefaults(defineProps<{ status?: 'create' | 'view' | 'edit' }>(),
    {
      status: 'create',
    }
)

async function requestData({name, raw}: UploadFile) {
  if (raw == null) return Promise.reject()
  let res = await AppApi.obtainPresignedUrl(name)
  const avatar = formGroup.get('avatar')
  avatar?.setValue('/' + res.data.bucketName + '/' + res.data.objectName)
  delete res.data.bucketName
  delete res.data.objectName
  return Promise.resolve(res.data)
}

const pagination = reactive<G.Pagination>({
  current: 1,
  size: 100,
  total: 0,
})

const searchForm = useFormGroup<RoleTypes.SearchForm>({
  roleCode: [ undefined ],
  roleName: [ undefined ]
})

const tenantList = ref<TenantTypes.Tenant[]>([])

function searchHandler() {
  paging()
}

function paging() {
  tableSpin.value = true
  RoleApi.paging(searchForm.getValue(), {...pagination})
      .then(res => {
        pagination.current = res.data.current
        pagination.size = res.data.size
        pagination.total = res.data.total
        datasource.value = res.data.records.map(it => {
          return {
            key: it.id,
            ...it
          }
        })
      })
      .finally(() => {
        tableSpin.value = false
      })
}

function pagingChangeHandler() {
  paging()
}

const formGroup = useFormGroup<UserTypes.SysUser>({
  nickname: [ undefined, Validators.required ],
  avatar: [ undefined ],
  gender: [ undefined ],
  tenantId: [ undefined ],
  account: {
    username: [ undefined, Validators.required ],
    email: [ undefined ],
    phone: [ undefined ],
    secret: [ undefined ]
  },
})

const datasource = ref<TreeSelectNode[]>()
const tableSpin = ref(false)
const selectedRowKeys = ref<VKey[]>([])
const columns = computed<TableColumn<RoleTypes.SysRole>[]>(() => ([
  {
    type: 'selectable',
    disabled() {
      return props.status === 'view'
    },
    menus: [
      'all',
      'invert',
      'none',
      'pageInvert'
    ]
  },
  {
    type: 'indexable',
    title: '#'
  },
  {
    title: '角色编码',
    dataKey: 'roleCode',
  },
  {
    title: '角色名称',
    dataKey: 'roleName',
  },
  {
    title: '备注',
    dataKey: 'memo',
  },
]))

const genderDataSource = computed<SelectData[]>(() => Object.entries(Gender).map(([ key, label ]) => ({key, label})))

const files = ref<UploadFile []>()


function updateFormStatus() {
  if (props.status === 'view') {
    formGroup.disable()
  } else if (props.status === 'edit') {
    formGroup.enable()
  }
}

watch(() => props.status, updateFormStatus)

defineExpose({
  getValue() {
    return Utils.clone<UserTypes.SysUser>({...formGroup.getValue(), roles: selectedRowKeys.value.map(it => ({id: it as string}))})
  },
  setValue(data: UserTypes.SysUser) {
    formGroup.setValue(data)
    if (data.avatar != null) {
      files.value = [ {
        key: data.avatar,
        name: data.avatar,
        thumbUrl: AppApi.fileUrl(data.avatar),
      } ]
    }
    if (data.roles != null) {
      selectedRowKeys.value = data.roles.map(it => it.id as string)
    }
  },
  reset() {
    formGroup.reset()
    paging()
    selectedRowKeys.value = []
  }
})

onMounted(() => {
  updateFormStatus()
  paging()
  TenantApi.list()
      .then(({data}) => {
        tenantList.value = data
      })
})

</script>

<style lang="stylus" scoped>
.data-form {
  width 100%
  padding 1rem
  margin 1rem 0

  :deep(.ix-row) {
    margin .5rem 0
  }
}

</style>
