<template>
    <div class="page-apply">
        <PageTitle :title="$L('应用')"/>

        <div class="apply-wrapper">
            <div class="apply-head">
                <div class="apply-nav">
                    <h1>{{ $L('应用') }}</h1>
                </div>
                <div class="apply-nav-actions">
                    <Dropdown trigger="click" placement="bottom-end" transfer @on-click="handleActionMenu">
                        <div class="apply-action-btn">
                            <Icon type="ios-more"/>
                        </div>
                        <DropdownMenu slot="list">
                            <DropdownItem v-if="!sortingMode" name="sort">{{ $L('调整排序') }}</DropdownItem>
                            <DropdownItem v-else name="cancelSort">{{ $L('退出排序') }}</DropdownItem>
                        </DropdownMenu>
                    </Dropdown>
                </div>
            </div>

            <div v-if="sortingMode" class="apply-sort-bar">
                <div class="apply-sort-tip">
                    <Icon type="md-move"/>
                    <span>{{ $L('拖动卡片调整顺序，保存后仅自己可见') }}</span>
                </div>
                <div class="apply-sort-actions">
                    <Button @click="exitSortMode">{{ $L('取消') }}</Button>
                    <Button @click="restoreDefaultSort">{{ $L('恢复默认') }}</Button>
                    <Button
                        type="primary"
                        :disabled="!sortHasChanges"
                        :loading="appSortSaving"
                        @click="submitSort">
                        {{ $L('保存') }}
                    </Button>
                </div>
            </div>

            <div class="apply-content">
                <template v-for="t in applyTypes">
                    <template v-if="t === 'base' || adminAppItems.length > 0">
                        <div
                            v-if="(t === 'base' && isExistAdminList) || t === 'admin'"
                            class="apply-row-title">
                            {{ t === 'base' ? $L('常用') : $L('管理员') }}
                        </div>
                        <Draggable
                            v-for="cards in [currentCards(t)]"
                            :key="`apps_${t}`"
                            tag="Row"
                            class="apply-sort-list"
                            :list="cards"
                            :disabled="!sortingMode"
                            :component-data="{ props: { gutter: 16 } }"
                            :options="getDraggableOptions(t)">
                            <Col
                                v-for="card in cards"
                                :key="card.sortKey"
                                class="apply-col-wrapper"
                                :xs="{ span: 6 }"
                                :sm="{ span: 6 }"
                                :lg="{ span: 6 }"
                                :xl="{ span: 6 }"
                                :xxl="{ span: 3 }">
                                <div class="apply-col">
                                    <template v-if="card.category === 'micro'">
                                        <div class="apply-item" :class="{'is-sorting': sortingMode}" @click="handleCardClick(card)">
                                            <div class="logo">
                                                <div class="apply-icon no-dark-content" :style="{backgroundImage: `url(${card.micro.icon})`}"></div>
                                            </div>
                                            <p>{{ card.micro.label }}</p>
                                        </div>
                                    </template>
                                    <template v-else>
                                        <template v-if="card.system.value === 'exportManage' && !sortingMode">
                                            <div
                                                class="apply-item"
                                                :class="{'is-sorting': sortingMode}"
                                                @click="openExportMenu">
                                                <div class="logo">
                                                    <div class="apply-icon no-dark-content" :class="getLogoClass(card.system.value)"></div>
                                                </div>
                                                <p>{{ $L(card.system.label) }}</p>
                                            </div>
                                        </template>
                                        <div
                                            v-else
                                            class="apply-item"
                                            :class="{'is-sorting': sortingMode}"
                                            @click="handleCardClick(card)">
                                            <div class="logo">
                                                <div class="apply-icon no-dark-content" :class="getLogoClass(card.system.value)"></div>
                                                <div
                                                    v-if="!sortingMode"
                                                    @click.stop="handleCardClick(card, 'badge')"
                                                    class="apply-box-top-report">
                                                    <Badge v-if="showBadge(card.system,'approve')" :overflow-count="999" :count="approveUnreadNumber"/>
                                                    <Badge v-if="showBadge(card.system,'report')" :overflow-count="999" :count="reportUnreadNumber"/>
                                                </div>
                                            </div>
                                            <p>{{ $L(card.system.label) }}</p>
                                        </div>
                                    </template>
                                </div>
                            </Col>
                        </Draggable>
                    </template>
                </template>
            </div>
        </div>

        <!--MY BOT-->
        <DrawerOverlay v-model="mybotShow" placement="right" :size="720">
            <template v-if="mybotShow" #title>
                {{ $L('我的机器人') }}
            </template>
            <template v-if="mybotShow" #more>
                <a href="javascript:void(0)" @click="applyClick({value: 'mybot-add'}, {id: 0})">{{ $L('添加机器人') }}</a>
            </template>
            <div v-if="mybotShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body full-body">
                    <div v-if="mybotList.length === 0" class="empty-data">
                        <Loading v-if="mybotLoad"/>
                        <span v-else>{{ $L('您没有创建机器人') }}</span>
                    </div>
                    <ul v-else class="ivu-modal-wrap-ul">
                        <li v-for="(item, key) in mybotList" :key="key">
                            <div class="modal-item-img">
                                <img :src="item.avatar">
                            </div>
                            <div class="modal-item-info">
                                <div class="modal-item-name">
                                    <h4 class="user-select-auto">{{ item.name }}</h4>
                                </div>
                                <div class="modal-item-mybot user-select-auto">
                                    <p><span>ID:</span>{{ item.id }}</p>
                                    <p><span>{{ $L('清理时间') }}:</span>{{ item.clear_day }}</p>
                                    <p><span>Webhook:</span>{{ item.webhook_url || '-' }}</p>
                                    <p><span>{{ $L('Webhook事件') }}:</span>{{ formatWebhookEvents(item.webhook_events) }}</p>
                                </div>
                                <div class="modal-item-btns">
                                    <Button icon="md-chatbubbles" @click="applyClick({value: 'mybot-chat'}, item)">{{ $L('开始聊天') }}</Button>
                                    <Button icon="md-create" @click="applyClick({value: 'mybot-add'}, item)">{{ $L('修改') }}</Button>
                                    <Button icon="md-trash" @click="applyClick({value: 'mybot-del'}, item)">{{ $L('删除') }}</Button>
                                </div>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </DrawerOverlay>

        <!--MY BOT 设置-->
        <Modal
            v-model="mybotModifyShow"
            :title="$L(mybotModifyData.id > 0 ? '修改机器人' : '添加机器人')"
            :mask-closable="false">
            <Form :model="mybotModifyData" v-bind="formOptions" @submit.native.prevent>
                <Alert v-if="mybotModifyData.system_name" type="error" style="margin-bottom:18px">{{ $L(`正在修改系统机器人：${mybotModifyData.system_name}`) }}</Alert>
                <FormItem prop="avatar" :label="$L('头像')">
                    <ImgUpload v-model="mybotModifyData.avatar" :num="1" :width="512" :height="512" whcut="cover"/>
                </FormItem>
                <FormItem prop="name" :label="$L('名称')">
                    <Input v-model="mybotModifyData.name" :maxlength="20" :placeholder="$L('机器人名称')"/>
                </FormItem>
                <FormItem prop="clear_day" :label="$L('消息保留')">
                    <Input v-model="mybotModifyData.clear_day" :maxlength="3" type="number" :placeholder="$L('默认：90天')">
                        <div slot="append">{{ $L('天') }}</div>
                    </Input>
                </FormItem>
                <FormItem prop="webhook_url" label="Webhook">
                    <Input v-model="mybotModifyData.webhook_url" :maxlength="255" :show-word-limit="0.9" type="textarea" placeholder="Webhook"/>
                </FormItem>
                <FormItem prop="webhook_events" :label="$L('Webhook事件')">
                    <CheckboxGroup v-model="mybotModifyData.webhook_events">
                        <Checkbox v-for="option in webhookEventOptions" :key="option.value" :label="option.value">
                            {{ $L(option.label) }}
                        </Checkbox>
                    </CheckboxGroup>
                </FormItem>
            </Form>
            <div slot="footer" class="adaption">
                <Button type="default" @click="mybotModifyShow=false">{{ $L('取消') }}</Button>
                <Button type="primary" :loading="mybotModifyLoad > 0" @click="onMybotModify">{{ $L('保存') }}</Button>
            </div>
        </Modal>

        <!--签到-->
        <DrawerOverlay v-model="signInShow" placement="right" :size="500">
            <template v-if="signInShow" #title>
                {{ $L('签到管理') }}
            </template>
            <template v-if="signInShow" #more>
                <a href="javascript:void(0)" @click="signInSettingShow=true" v-if="userIsAdmin">{{ $L('签到设置') }}</a>
            </template>
            <div v-if="signInShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body">
                    <Checkin/>
                </div>
            </div>
        </DrawerOverlay>

        <!--签到设置-->
        <DrawerOverlay v-model="signInSettingShow" placement="right" :size="720">
            <template v-if="signInSettingShow" #title>
                {{ $L('签到设置') }}
            </template>
            <div v-if="signInSettingShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body">
                    <SystemCheckin/>
                </div>
            </div>
        </DrawerOverlay>

        <!--会议-->
        <DrawerOverlay v-model="meetingShow" placement="right" :size="720">
            <template v-if="meetingShow" #title>
                {{ $L('会议') }}
            </template>
            <template v-if="meetingShow" #more>
                <a href="javascript:void(0)" @click="meetingSettingShow = true" v-if="userIsAdmin">{{ $L('会议设置') }}</a>
            </template>
            <div v-if="meetingShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body full-body">
                    <SystemMeetingNav @openDetail="openDetail" @onMeeting="onMeeting"/>
                </div>
            </div>
        </DrawerOverlay>

        <!--会议设置-->
        <DrawerOverlay v-model="meetingSettingShow" placement="right" :size="600">
            <template v-if="meetingSettingShow" #title>
                {{ $L('会议设置') }}
            </template>
            <div v-if="meetingSettingShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body full-body">
                    <SystemMeeting/>
                </div>
            </div>
        </DrawerOverlay>

        <!--LDAP-->
        <DrawerOverlay v-model="ldapShow" placement="right" :size="700">
            <template v-if="ldapShow" #title>
                {{ $L('LDAP 设置') }}
            </template>
            <div v-if="ldapShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body">
                    <SystemThirdAccess/>
                </div>
            </div>
        </DrawerOverlay>

        <!--邮件-->
        <DrawerOverlay v-model="mailShow" placement="right" :size="700">
            <template v-if="mailShow" #title>
                {{ $L('邮件通知') }}
            </template>
            <div v-if="mailShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body">
                    <SystemEmailSetting/>
                </div>
            </div>
        </DrawerOverlay>

        <!--App 推送-->
        <DrawerOverlay v-model="appPushShow" placement="right" :size="700">
            <template v-if="appPushShow" #title>
                {{ $L('APP 推送') }}
            </template>
            <div v-if="appPushShow" class="ivu-modal-wrap-apply">
                <div class="ivu-modal-wrap-apply-body">
                    <SystemAppPush/>
                </div>
            </div>
        </DrawerOverlay>

        <!--扫码登录-->
        <Modal
            v-model="scanLoginShow"
            :title="$L('扫码登录')"
            :mask-closable="false">
            <div class="mobile-scan-login-box">
                <div class="mobile-scan-login-title">{{ $L(`你好，扫码确认登录`) }}</div>
                <div class="mobile-scan-login-subtitle">「{{ $L('为确保帐号安全，请确认是本人操作') }}」</div>
            </div>
            <div slot="footer" class="adaption">
                <Button type="default" @click="scanLoginShow=false">{{ $L('取消登录') }}</Button>
                <Button type="primary" :loading="scanLoginLoad" @click="scanLoginSubmit">{{ $L('确认登录') }}</Button>
            </div>
        </Modal>

        <!--发起群投票、接龙-->
        <UserSelect
            ref="wordChainAndVoteRef"
            v-model="sendData"
            :multiple-max="1"
            :title="sendType == 'vote' ? $L('选择群组发起投票') : $L('选择群组发起接龙')"
            :before-submit="goWordChainAndVote"
            :show-select-all="false"
            :only-group="true"
            show-dialog
            module/>

    </div>
</template>

<script>
import {mapGetters, mapState} from "vuex";
import DrawerOverlay from "../../components/DrawerOverlay";
import UserSelect from "../../components/UserSelect";
import SystemCheckin from "./setting/components/SystemCheckin";
import Checkin from "./setting/checkin";
import SystemMeeting from "./setting/components/SystemMeeting";
import SystemMeetingNav from "./setting/components/SystemMeetingNav.vue";
import SystemThirdAccess from "./setting/components/SystemThirdAccess";
import SystemEmailSetting from "./setting/components/SystemEmailSetting";
import SystemAppPush from "./setting/components/SystemAppPush";
import emitter from "../../store/events";
import ImgUpload from "../../components/ImgUpload.vue";
import {webhookEventOptions} from "../../utils/webhook";
import Draggable from "vuedraggable";

export default {
    components: {
        Draggable,
        ImgUpload,
        UserSelect,
        DrawerOverlay,
        SystemCheckin,
        Checkin,
        SystemMeeting,
        SystemMeetingNav,
        SystemThirdAccess,
        SystemEmailSetting,
        SystemAppPush
    },
    data() {
        return {
            applyTypes: ['base', 'admin'],
            sortingMode: false,
            sortLists: {
                base: [],
                admin: [],
            },
            sortInitialLists: {
                base: [],
                admin: [],
            },
            appSorts: {
                base: [],
                admin: [],
            },
            appSortLoaded: false,
            appSortLoading: false,
            appSortSaving: false,
            //
            mybotShow: false,
            mybotList: [],
            mybotLoad: 0,
            mybotModifyShow: false,
            mybotModifyData: {},
            mybotModifyLoad: 0,
            webhookEventOptions,
            //
            signInShow: false,
            signInSettingShow: false,
            //
            meetingShow: false,
            meetingSettingShow: false,
            //
            ldapShow: false,
            //
            mailShow: false,
            //
            appPushShow: false,
            //
            scanLoginShow: false,
            scanLoginLoad: false,
            scanLoginCode: '',
            //
            sendData: [],
            sendType: '',
        }
    },
    created() {
        this.fetchAppSorts();
    },
    activated() {
        this.$store.dispatch("updateMicroAppsStatus")
    },
    computed: {
        ...mapState([
            'systemConfig',
            'userInfo',
            'userIsAdmin',
            'reportUnreadNumber',
            'approveUnreadNumber',
            'cacheDialogs',
            'windowOrientation',
            'windowPortrait',
            'formOptions',
            'routeLoading',
            'microAppsIds'
        ]),
        ...mapGetters([
            'filterMicroAppsMenus',
            'filterMicroAppsMenusAdmin',
        ]),
        applyList() {
            const list = [
                // 常用应用
                {value: "approve", label: "审批中心", sort: 30, show: this.microAppsIds.includes('approve')},
                {value: "favorite", label: "我的收藏", sort: 45},
                {value: "recent", label: "最近打开", sort: 47},
                {value: "report", label: "工作报告", sort: 50},
                {value: "mybot", label: "我的机器人", sort: 55},
                {value: "signin", label: "签到打卡", sort: 70},
                {value: "meeting", label: "在线会议", sort: 80},
                {value: "createGroup", label: "创建群组", sort: 85},
                {value: "word-chain", label: "群接龙", sort: 90},
                {value: "vote", label: "群投票", sort: 100},
                {value: "addProject", label: "创建项目", sort: 110},
                {value: "addTask", label: "添加任务", sort: 120},
                {value: "scan", label: "扫一扫", sort: 130, show: $A.isEEUIApp},

                // 管理员应用
                {type: 'admin', value: "ldap", label: "LDAP", sort: 160, show: this.userIsAdmin},
                {type: 'admin', value: "mail", label: "邮件通知", sort: 170, show: this.userIsAdmin},
                {type: 'admin', value: "appPush", label: "APP 推送", sort: 180, show: this.userIsAdmin},
                {type: 'admin', value: "complaint", label: "举报管理", sort: 190, show: this.userIsAdmin},
                {type: 'admin', value: "exportManage", label: "数据导出", sort: 195, show: this.userIsAdmin},
                {type: 'admin', value: "allUser", label: "团队管理", sort: 200, show: this.userIsAdmin},
            ]
            // 竖屏模式
            if (this.windowPortrait) {
                list.push(...[
                    {value: "calendar", label: "日历", sort: 10},
                    {value: "file", label: "文件", sort: 20},
                    {value: "setting", label: "设置", sort: 140},
                ])
            }
            //
            return list.sort((a, b) => a.sort - b.sort);
        },
        isExistAdminList() {
            return this.adminAppItems.length > 0;
        },
        baseAppItems() {
            return this.applySavedSort(this.collectAppItems('base'), 'base');
        },
        adminAppItems() {
            return this.applySavedSort(this.collectAppItems('admin'), 'admin');
        },
        sortHasChanges() {
            if (!this.sortingMode) {
                return false;
            }
            const groups = ['base', 'admin'];
            return groups.some(group => {
                const current = (this.sortLists[group] || []).map(item => item.sortKey);
                const initial = this.sortInitialLists[group] || [];
                if (current.length !== initial.length) {
                    return true;
                }
                return current.some((key, index) => key !== initial[index]);
            });
        }
    },
    watch: {
        sortingMode(val) {
            if (val) {
                this.bootstrapSortLists();
            } else {
                this.resetSortState();
            }
        },
        baseAppItems() {
            if (this.sortingMode) {
                this.mergeSortListWithSource('base');
            }
        },
        adminAppItems() {
            if (this.sortingMode) {
                this.mergeSortListWithSource('admin');
            }
        }
    },
    methods: {
        handleActionMenu(action) {
            if (action === 'sort') {
                this.enterSortMode();
            } else if (action === 'cancelSort') {
                this.exitSortMode();
            }
        },
        currentCards(type) {
            return this.sortingMode ? (this.sortLists[type] || []) : this.getDisplayItems(type);
        },
        getDisplayItems(type) {
            return type === 'admin' ? this.adminAppItems : this.baseAppItems;
        },
        collectAppItems(group) {
            const items = [];
            const microSource = group === 'admin' ? this.filterMicroAppsMenusAdmin : this.filterMicroAppsMenus;
            microSource.forEach(menu => {
                if (!menu || menu.show === false) {
                    return;
                }
                items.push(this.createMicroCard(menu, group));
            });
            this.applyList.forEach(item => {
                if (item.show === false) {
                    return;
                }
                const isAdminItem = item.type === 'admin';
                if (group === 'admin') {
                    if (!isAdminItem) {
                        return;
                    }
                } else if (isAdminItem) {
                    return;
                }
                items.push(this.createSystemCard(item, group));
            });
            return items;
        },
        createMicroCard(menu, group) {
            const fallback = menu?.id || menu?.value || menu?.url || menu?.label || 'unknown';
            const key = menu?.name || fallback;
            return {
                sortKey: `micro:${key}`,
                category: 'micro',
                group,
                micro: menu,
            };
        },
        createSystemCard(item, group) {
            return {
                sortKey: `system:${item.value}`,
                category: 'system',
                group,
                system: item,
            };
        },
        applySavedSort(items, group) {
            const saved = this.appSorts[group] || [];
            if (!saved.length) {
                return items;
            }
            const map = {};
            items.forEach(card => {
                map[card.sortKey] = card;
            });
            const ordered = [];
            saved.forEach(key => {
                if (map[key]) {
                    ordered.push(map[key]);
                    delete map[key];
                }
            });
            items.forEach(card => {
                if (map[card.sortKey]) {
                    ordered.push(card);
                    delete map[card.sortKey];
                }
            });
            return ordered;
        },
        async enterSortMode() {
            if (this.sortingMode) {
                return;
            }
            if (!this.appSortLoaded && !this.appSortLoading) {
                await this.fetchAppSorts();
            }
            this.sortingMode = true;
        },
        exitSortMode() {
            this.sortingMode = false;
        },
        bootstrapSortLists() {
            const base = this.cloneAppItems(this.baseAppItems);
            const admin = this.cloneAppItems(this.adminAppItems);
            this.$set(this.sortLists, 'base', base);
            this.$set(this.sortLists, 'admin', admin);
            this.$set(this.sortInitialLists, 'base', base.map(item => item.sortKey));
            this.$set(this.sortInitialLists, 'admin', admin.map(item => item.sortKey));
        },
        resetSortState() {
            this.$set(this.sortLists, 'base', []);
            this.$set(this.sortLists, 'admin', []);
            this.$set(this.sortInitialLists, 'base', []);
            this.$set(this.sortInitialLists, 'admin', []);
        },
        mergeSortListWithSource(group) {
            const source = this.cloneAppItems(this.getDisplayItems(group));
            if (!source.length) {
                this.$set(this.sortLists, group, []);
                this.$set(this.sortInitialLists, group, []);
                return;
            }
            const sourceMap = new Map(source.map(item => [item.sortKey, item]));
            const next = [];
            (this.sortLists[group] || []).forEach(item => {
                if (sourceMap.has(item.sortKey)) {
                    next.push(sourceMap.get(item.sortKey));
                    sourceMap.delete(item.sortKey);
                }
            });
            sourceMap.forEach(item => next.push(item));
            this.$set(this.sortLists, group, this.cloneAppItems(next));
            const snapshot = this.sortInitialLists[group] ? [...this.sortInitialLists[group]] : [];
            next.forEach(item => {
                if (!snapshot.includes(item.sortKey)) {
                    snapshot.push(item.sortKey);
                }
            });
            this.$set(this.sortInitialLists, group, snapshot);
        },
        cloneAppItems(items = []) {
            return items.map(item => Object.assign({}, item));
        },
        getDraggableOptions(type) {
            return {
                animation: 200,
                draggable: '.apply-col-wrapper',
                group: {
                    name: `${type}-apps`,
                    pull: false,
                    put: false,
                }
            };
        },
        async fetchAppSorts() {
            if (this.appSortLoading) {
                return;
            }
            this.appSortLoading = true;
            try {
                const {data} = await this.$store.dispatch("call", {
                    url: 'users/appsort',
                    method: 'get',
                });
                this.appSorts = this.normalizeSortPayload(data?.sorts);
            } catch (error) {
                console.warn(error?.msg || error);
            } finally {
                this.appSortLoading = false;
                this.appSortLoaded = true;
            }
        },
        normalizeSortPayload(raw) {
            const result = {base: [], admin: []};
            if (!raw || typeof raw !== 'object') {
                return result;
            }
            ['base', 'admin'].forEach(group => {
                const list = Array.isArray(raw[group]) ? raw[group] : [];
                result[group] = list
                    .filter(item => typeof item === 'string')
                    .map(item => item.trim())
                    .filter(item => item.length > 0);
            });
            return result;
        },
        submitSort() {
            if (!this.sortHasChanges) {
                this.exitSortMode();
                return;
            }
            const payload = this.buildSortPayload();
            this.appSortSaving = true;
            this.$store.dispatch("call", {
                url: 'users/appsort/save',
                method: 'post',
                data: {
                    sorts: payload,
                }
            }).then(({data, msg}) => {
                this.appSorts = this.normalizeSortPayload(data?.sorts || payload);
                this.exitSortMode();
                $A.messageSuccess(msg || this.$L('保存成功'));
            }).catch(({msg}) => {
                $A.modalError(msg || this.$L('保存失败'));
            }).finally(() => {
                this.appSortSaving = false;
            });
        },
        restoreDefaultSort() {
            if (!this.sortingMode) {
                return;
            }
            ['base', 'admin'].forEach(group => {
                this.$set(this.sortLists, group, this.cloneAppItems(this.collectAppItems(group)));
            });
        },
        buildSortPayload() {
            const payload = {base: [], admin: []};
            ['base', 'admin'].forEach(group => {
                const keys = (this.sortLists[group] || []).map(item => item.sortKey);
                const defaults = this.getDefaultSortKeys(group);
                payload[group] = this.arraysEqual(keys, defaults) ? [] : keys;
            });
            return payload;
        },
        getDefaultSortKeys(group) {
            return this.collectAppItems(group).map(item => item.sortKey);
        },
        arraysEqual(a = [], b = []) {
            if (a.length !== b.length) {
                return false;
            }
            return a.every((item, index) => item === b[index]);
        },
        handleCardClick(card, params = '') {
            if (this.sortingMode) {
                return;
            }
            if (!card) {
                return;
            }
            if (card.category === 'micro') {
                this.applyClick({value: 'microApp'}, card.micro);
                return;
            }
            this.applyClick(card.system, params);
        },
        openExportMenu({currentTarget: target} = {}) {
            if (this.sortingMode) {
                return;
            }
            if (target && typeof target.stopPropagation === 'function') {
                target.stopPropagation();
            }
            const reference = target && target.target ? target.target : target;
            const menuEvent = target && target.target ? target : (reference ? {target: reference} : target);
            const list = [
                {label: this.$L('导出任务统计'), value: 'task'},
                {label: this.$L('导出超期任务'), value: 'overdue'},
                {label: this.$L('导出审批数据'), value: 'approve'},
                {label: this.$L('导出签到数据'), value: 'checkin'},
            ];
            this.$store.commit('menu/operation', {
                event: menuEvent,
                list,
                size: 'large',
                onUpdate: (type) => {
                    if (type) {
                        this.handleExport(type);
                    }
                }
            });
        },
        normalizeWebhookEvents(events = [], useFallback = false) {
            if (!Array.isArray(events)) {
                events = events ? [events] : [];
            }
            const allowed = this.webhookEventOptions.map(item => item.value);
            const result = events.filter(item => allowed.includes(item));
            if (result.length) {
                return Array.from(new Set(result));
            }
            return [];
        },
        enhanceMybotItem(item = {}) {
            const data = $A.cloneJSON(item || {});
            let events = data.webhook_events;
            if (typeof events === 'undefined' || events === null) {
                events = [];
            }
            events = this.normalizeWebhookEvents(events, false);
            if (!events.length) {
                events = [];
            }
            data.webhook_events = events;
            return data;
        },
        formatWebhookEvents(events) {
            const values = this.normalizeWebhookEvents(events, false);
            const labels = this.webhookEventOptions
                .filter(option => values.includes(option.value))
                .map(option => this.$L(option.label));
            return labels.length ? labels.join('、') : '-';
        },
        getLogoClass(name) {
            name = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
            return name
        },
        showBadge(item, type) {
            let num = 0;
            switch (type) {
                case 'approve':
                    num = this.approveUnreadNumber;
                    break;
                case 'report':
                    num = this.reportUnreadNumber;
                    break;
            }
            return item.value == type && num > 0
        },
        // 点击应用
        applyClick(item, params = '') {
            switch (item.value) {
                case 'calendar':
                case 'file':
                case 'setting':
                    this.goForward({name: 'manage-' + item.value});
                    break;
                case 'report':
                    emitter.emit('openReport', params == 'badge' ? 'receive' : 'my');
                    break;
                case 'favorite':
                    emitter.emit('openFavorite');
                    break;
                case 'recent':
                    emitter.emit('openRecent');
                    break;
                case 'mybot':
                    this.getMybot();
                    this.mybotShow = true;
                    break;
                case 'mybot-chat':
                    this.chatMybot(params.id);
                    break;
                case 'mybot-add':
                    this.addMybot(params);
                    break;
                case 'mybot-del':
                    this.delMybot(params);
                    break;
                case 'signin':
                    this.signInShow = true;
                    break;
                case 'meeting':
                    this.meetingShow = true;
                    break;
                case 'ldap':
                    this.ldapShow = true;
                    break;
                case 'mail':
                    this.mailShow = true;
                    break;
                case 'appPush':
                    this.appPushShow = true;
                    break;
                case 'scan':
                    $A.eeuiAppScan(this.scanResult);
                    break;
                case 'word-chain':
                case 'vote':
                    this.sendData = [];
                    this.sendType = item.value;
                    this.$refs.wordChainAndVoteRef.onSelection()
                    break;

            }
            this.$emit("on-click", item.value, params);
        },
        handleExport(type) {
            emitter.emit('openManageExport', type);
        },
        // 获取我的机器人
        getMybot() {
            this.mybotLoad++
            this.$store.dispatch("call", {
                url: 'users/bot/list',
            }).then(({data}) => {
                this.mybotList = (data.list || []).map(item => this.enhanceMybotItem(item));
            }).finally(_ => {
                this.mybotLoad--
            });
        },
        // 与我的机器人聊天
        chatMybot(userid) {
            this.$store.dispatch("openDialogUserid", userid).catch(({msg}) => {
                $A.modalError(msg || this.$L('打开会话失败'))
            });
        },
        // 添加修改我的机器人
        addMybot(info) {
            this.mybotModifyData = this.enhanceMybotItem(info)
            this.mybotModifyShow = true;
        },
        // 删除我的机器人
        delMybot(info) {
            $A.modalInput({
                title: `删除机器人：${info.name}`,
                placeholder: `请输入备注原因`,
                okText: "删除",
                okType: "error",
                onOk: remark => {
                    if (!remark) {
                        return `请输入备注原因`
                    }
                    return new Promise((resolve, reject) => {
                        this.$store.dispatch("call", {
                            url: 'users/bot/delete',
                            data: {
                                id: info.id,
                                remark
                            }
                        }).then(({msg}) => {
                            const index = this.mybotList.findIndex(item => item.id === info.id);
                            if (index > -1) {
                                this.mybotList.splice(index, 1);
                            }
                            $A.messageSuccess(msg);
                            resolve();
                        }).catch(({msg}) => {
                            reject(msg);
                        });
                    })
                }
            });
        },
        // 添加/修改我的机器人
        onMybotModify() {
            this.mybotModifyLoad++
            this.$store.dispatch("editUserBot", this.mybotModifyData).then(({data, msg}) => {
                const botData = this.enhanceMybotItem(data);
                const index = this.mybotList.findIndex(item => item.id === botData.id);
                if (index > -1) {
                    this.mybotList.splice(index, 1, botData);
                } else {
                    this.mybotList.unshift(botData);
                }
                this.mybotModifyShow = false;
                this.mybotModifyData = {};
                $A.messageSuccess(msg);
            }).catch(({msg}) => {
                $A.modalError(msg);
            }).finally(_ => {
                this.mybotModifyLoad--;
            });
        },
        // 会议
        onMeeting(name) {
            switch (name) {
                case 'createMeeting':
                    emitter.emit('addMeeting', {
                        type: 'create',
                        userids: [this.userId],
                    });
                    break;
                case 'joinMeeting':
                    emitter.emit('addMeeting', {
                        type: 'join',
                    });
                    break;
            }
        },
        // 扫一扫
        scanResult(text) {
            const arr = (text + "").match(/^https?:\/\/(.*?)\/login\?qrcode=(.*?)$/)
            if (arr) {
                // 扫码登录
                if ($A.getDomain(text) != $A.getDomain($A.mainUrl())) {
                    let content = this.$L('请确认扫码的服务器与当前服务器一致')
                    content += `<br/>${this.$L('二维码服务器')}: ${$A.getDomain(text)}`
                    content += `<br/>${this.$L('当前服务器')}: ${$A.getDomain($A.mainUrl())}`
                    $A.modalWarning({
                        language: false,
                        title: this.$L('扫码登录'),
                        content
                    })
                    return
                }
                this.scanLoginCode = arr[2];
                this.scanLoginShow = true;
                return
            }
            if (/^https?:\/\//i.test(text)) {
                // 打开链接
                this.$store.dispatch('openAppChildPage', {
                    pageType: 'app',
                    pageTitle: ' ',
                    url: 'web.js',
                    params: {
                        url: text
                    },
                });
            } else {
                // 其他文本
                $A.modalInfo({
                    title: this.$L('扫描结果'),
                    content: text,
                    width: 400,
                });
            }
        },
        // 扫描登录提交
        scanLoginSubmit() {
            if (this.scanLoginLoad === true) {
                return
            }
            this.scanLoginLoad = true
            //
            this.$store.dispatch("call", {
                url: "users/login/qrcode",
                data: {
                    type: "login",
                    code: this.scanLoginCode,
                }
            }).then(({msg}) => {
                this.scanLoginShow = false
                $A.messageSuccess(msg)
            }).catch(({msg}) => {
                $A.messageError(msg)
            }).finally(_ => {
                this.scanLoginLoad = false
            });
        },
        // 打开明细
        openDetail(desc) {
            $A.modalInfo({
                content: desc,
            });
        },
        // 前往接龙与投票
        goWordChainAndVote() {
            return new Promise((resolve, reject) => {
                if (this.sendData.length === 0) {
                    $A.messageError("请选择对话或成员");
                    reject()
                    return
                }
                const dialog_id = Number(this.sendData[0].replace('d:', ''))
                this.$store.dispatch("openDialog", dialog_id).then(async () => {
                    await new Promise(resolve => setTimeout(resolve, 300));
                    requestAnimationFrame(_ => {
                        const type = this.sendType == 'word-chain' ? 'dialogDroupWordChain' : 'dialogGroupVote'
                        this.$store.state[type] = {type: 'create', dialog_id: dialog_id}
                    })
                })
                resolve()
            })
        }
    }
}
</script>
