<!-- 同步用户 -->
<template>
  <div>
    <Modal v-model:visible="_vis" title="同步用户" :footer="null" @cancel="_vis = false" width="80%">
      <Row :gutter="10" class="model-body">
        <Col :span="4">
          <Input v-model:value="deptName" @keyup.enter="getDepartment" allowClear placeholder="请输入部门名称" style="margin-bottom: 8px">
            <template #addonAfter>
              <AIcon type="SearchOutlined" style="cursor: pointer" @click="getDepartment" />
            </template>
          </Input>
          <JTree :tree-data="deptTreeData" :fieldNames="{ title: 'name', key: 'id' }" :selectedKeys="[deptId]" @select="onTreeSelect" />
          <Empty v-if="!deptTreeData.length" />
        </Col>
        <Col :span="20">
          <JButton type="primary" @click="handleAutoBind"> 自动绑定 </JButton>
          <JTable
            ref="tableRef"
            :columns="columns"
            :dataSource="dataSource"
            :loading="tableLoading"
            :pagination="{
              total: dataSource.length,
              current: current,
              pageSize: pageSize,
              pageSizeOptions: ['10', '20', '50', '100'],
              showSizeChanger: true,
              hideOnSinglePage: false,
              showTotal: (total: number, range: number) => `第 ${range[0]} - ${range[1]} 条/总共 ${total} 条`,
            }"
            @change="handleTableChange"
          >
            <template #bodyCell="{ column, record, index }">
              <template v-if="column.dataIndex === 'status'">
                <Space>
                  <Badge :status="record.status.value" :text="record.status.text" />
                </Space>
              </template>
              <template v-if="column.dataIndex === 'action'">
                <Space :size="16">
                  <Tooltip v-for="i in getActions(record, 'table')" :key="i.key" v-bind="i.tooltip">
                    <Popconfirm v-if="i.popConfirm" v-bind="i.popConfirm" :disabled="i.disabled">
                      <JButton :disabled="i.disabled" style="padding: 0" type="link"><AIcon :type="i.icon" /></JButton>
                    </Popconfirm>
                    <JButton style="padding: 0" type="link" v-else @click="i.onClick && i.onClick(record)">
                      <JButton :disabled="i.disabled" style="padding: 0" type="link"><AIcon :type="i.icon" /></JButton>
                    </JButton>
                  </Tooltip>
                </Space>
              </template>
            </template>
          </JTable>
        </Col>
      </Row>
    </Modal>

    <!-- 绑定用户 -->
    <Modal
      v-model:visible="bindVis"
      title="绑定用户"
      :maskClosable="false"
      :confirm-loading="confirmLoading"
      @cancel="handleCancel"
      @ok="handleBindSubmit"
    >
      <Form layout="vertical">
        <FormItem label="用户" v-bind="validateInfos.userId">
          <Select
            v-model:value="formData.userId"
            :options="allUserList"
            allowClear
            show-search
            option-filter-prop="children"
            :filter-option="filterOption"
            placeholder="请选择用户"
          />
        </FormItem>
      </Form>
    </Modal>
  </div>
</template>

<script setup lang="ts" name="SyncUser">
  import configApi from '../../../../api/notice/config';
  import { PropType, computed, watch, ref } from 'vue';
  // @ts-ignore
  import { message, Modal, Row, Col, Form, FormItem, Select, Space, Badge, Tooltip, Popconfirm, Button as JButton, Tree as JTree, Empty, AIcon, Input } from 'linker-ui-components';
  import type { ActionsType } from '../../../device/Instance/typings';

  const useForm = Form.useForm;

  type Emits = {
    (e: 'update:visible', data: boolean): void;
  };
  const emit = defineEmits<Emits>();

  const props = defineProps({
    visible: { type: Boolean, default: false },
    data: {
      type: Object as PropType<Partial<Record<string, any>>>,
      default: () => ({}),
    },
  });

  const _vis = computed({
    get: () => props.visible,
    set: (val) => emit('update:visible', val),
  });

  watch(
    () => _vis.value,
    (val) => {
      if (val) {
        getDepartment();
      } else {
        dataSource.value = [];
      }
    }
  );

  // 左侧部门
  const deptTreeData = ref([]);
  const deptName = ref('');
  const deptId = ref('');

  /**
   * 获取部门
   */
  const getDepartment = async () => {
    let res = null;
    // @ts-ignore
    if (props.data.type === 'dingTalk') {
      // @ts-ignore
      res = await configApi.dingTalkDept(props.data.id);
    }
    // @ts-ignore
    else if (props.data.type === 'weixin') {
      // @ts-ignore
      res = await configApi.weChatDept(props.data.id);
    }
    let _result = res?.result;
    if (deptName.value) {
      _result = res?.result?.filter((f: any) => f.name.indexOf(deptName.value) > -1);
    }

    deptTreeData.value = _result;
    deptId.value = _result[0]?.id;
  };

  watch(
    () => deptName.value,
    (val: any) => {
      if (!val) getDepartment();
    }
  );

  /**
   * 部门点击
   */
  const onTreeSelect = (keys: any) => {
    deptId.value = keys[0];
    pageSize.value = 10;
    current.value = 1;
  };

  // 右侧表格

  const columns = [
    {
      title: '钉钉用户名',
      dataIndex: 'thirdPartyUserName',
      key: 'thirdPartyUserName',
    },
    {
      title: '用户',
      dataIndex: 'userName',
      key: 'userName',
      scopedSlots: true,
    },
    {
      title: '绑定状态',
      dataIndex: 'status',
      key: 'status',
      scopedSlots: true,
    },
    {
      title: '操作',
      dataIndex: 'action',
      key: 'action',
      scopedSlots: true,
    },
  ];
  const getActions = (data: Partial<Record<string, any>>, type: 'card' | 'table'): ActionsType[] => {
    if (!data) return [];
    const actions = [
      {
        key: 'bind',
        text: '绑定',
        tooltip: {
          title: '绑定',
        },
        icon: 'EditOutlined',
        onClick: () => {
          handleBind(data);
        },
      },
      {
        key: 'unbind',
        text: '解绑',
        icon: 'DisconnectOutlined',
        popConfirm: {
          title: '确认解绑?',
          onConfirm: async () => {
            configApi.unBindUser({ bindingId: data.bindId }, data.bindId).then(() => {
              message.success('操作成功');
              getTableData();
            });
          },
        },
      },
    ];
    // @ts-ignore
    if (data.status.value === 'success') return actions;
    // @ts-ignore
    return actions.filter((i: ActionsType) => i.key !== 'unbind');
  };

  /**
   * 自动绑定
   */
  const handleAutoBind = async () => {
    await getTableData([
      {
        column: `id$user-third$${props.data.type}_${props.data.provider}$not`,
      },
    ]);
    const params = dataSource.value
      .filter((f: any) => f.userId && f.status.value === 'error')
      .map((m: any) => ({
        userId: m.userId,
        providerName: m.thirdPartyUserName,
        thirdPartyUserId: m.thirdPartyUserId,
      }));

    if (props.data.type === 'dingTalk') {
      configApi.dingTalkBindUser(params, props.data.id).then(() => {
        message.success('操作成功');
        getTableData();
      });
    } else if (props.data.type === 'weixin') {
      configApi.weChatBindUser(params, props.data.id).then(() => {
        message.success('操作成功');
        getTableData();
      });
    }
  };

  /**
   * 获取钉钉/微信部门用户
   */
  const getDeptUsers = async () => {
    let res = null;
    // @ts-ignore
    if (props.data.type === 'dingTalk') {
      res = await configApi.getDingTalkUsers(props.data.id, deptId.value);
    } else if (props.data.type === 'weixin') {
      res = await configApi.getWeChatUsers(props.data.id, deptId.value);
    }
    return res?.result;
  };
  /**
   * 获取已经绑定的用户
   */
  const getBindUsers = async () => {
    let res = null;
    if (props.data.type === 'dingTalk') {
      res = await configApi.getDingTalkBindUsers(props.data.id);
    } else if (props.data.type === 'weixin') {
      res = await configApi.getWeChatBindUsers(props.data.id);
    }
    return res?.result;
  };
  /**
   * 获取所有用户未绑定的用户
   */
  const allUserList = ref([]);
  const getAllUsers = async (terms?: any) => {
    const params = {
      paging: false,
      terms,
    };
    const { result } = await configApi.getPlatformUsers(params);
    if (result) {
      allUserList.value = result.map((m: any) => ({
        label: m.name,
        value: m.id,
        ...m,
      }));
    }
    return result;
  };

  /**
   * 处理列表数据
   */
  const dataSource = ref<any>([]);
  const tableLoading = ref(false);
  const getTableData = (terms?: any) => {
    tableLoading.value = true;
    Promise.all<any>([getDeptUsers(), getBindUsers(), getAllUsers(terms)])
      .then((res) => {
        dataSource.value = [];
        const [deptUsers, bindUsers, unBindUsers] = res;
        (deptUsers || []).forEach((deptUser: any) => {
          // 未绑定的用户
          let unBindUser = unBindUsers.find((f: any) => f.name === deptUser?.name);
          // 绑定的用户
          const bindUser = bindUsers.find((f: any) => f.thirdPartyUserId === deptUser.id);
          if (bindUser) {
            unBindUser = unBindUsers.find((f: any) => f.id === bindUser.userId);
          }
          dataSource.value.push({
            thirdPartyUserId: deptUser.id,
            thirdPartyUserName: deptUser.name,
            bindId: bindUser?.id,
            userId: unBindUser?.id,
            userName: unBindUser ? `${unBindUser.name}(${unBindUser.username})` : bindUser?.providerName,
            status: {
              text: bindUser?.providerName ? '已绑定' : '未绑定',
              value: bindUser?.providerName ? 'success' : 'error',
            },
          });
        });
        // console.log('dataSource.value: ', dataSource.value);
      })
      .finally(() => {
        tableLoading.value = false;
      });
  };

  /**
   * 前端分页
   */
  const current = ref(1);
  const pageSize = ref(10);
  const handleTableChange = (pagination: any) => {
    current.value = pagination.current;
    pageSize.value = pagination.pageSize;
  };

  watch(
    () => deptId.value,
    () => {
      getTableData();
    },
    { immediate: true }
  );

  /**
   * 绑定用户
   */
  const bindVis = ref(false);
  const confirmLoading = ref(false);
  const formData = ref({
    userId: '',
    thirdPartyUserId: '',
    thirdPartyUserName: '',
    bindId: '',
  });
  const formRules = ref({
    userId: [{ required: true, message: '请选择用户', trigger: 'change' }],
  });

  const { resetFields, validate, validateInfos, clearValidate } = useForm(formData.value, formRules.value);

  const handleBind = (row: any) => {
    bindVis.value = true;
    // formData.value = row;
    Object.assign(formData.value, row);
    getAllUsers([
      {
        column: `id$user-third$${props.data.type}_${props.data.provider}$not`,
      },
    ]);
  };

  /**
   * 绑定用户, 用户下拉筛选
   */
  const filterOption = (input: string, option: any) => {
    return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0;
  };

  /**
   * 绑定提交
   */
  const handleBindSubmit = () => {
    validate().then(async () => {
      const params = {
        providerName: formData.value.thirdPartyUserName,
        thirdPartyUserId: formData.value.thirdPartyUserId,
        userId: formData.value.userId,
        id: formData.value.bindId,
      };
      confirmLoading.value = true;
      if (props.data.type === 'dingTalk') {
        configApi
          .dingTalkBindUser([params], props.data.id)
          .then(() => {
            message.success('操作成功');
            bindVis.value = false;
            getTableData();
          })
          .finally(() => {
            confirmLoading.value = false;
          });
      } else if (props.data.type === 'weixin') {
        configApi
          .weChatBindUser([params], props.data.id)
          .then(() => {
            message.success('操作成功');
            bindVis.value = false;
            getTableData();
          })
          .finally(() => {
            confirmLoading.value = false;
          });
      }
    });
  };
  const handleCancel = () => {
    bindVis.value = false;
    resetFields();
  };
</script>

<style lang="less" scoped>
  .model-body {
    height: 600px;
    overflow-y: auto;
    &:deep(.ant-pagination-item) {
      display: none;
    }
  }
</style>
