<template>
    <div class="service-record">
        <div class="service-record-header">
            <span class="service-record-title">{{ t('服务记录') }}</span>
        </div>

        <div class="service-record-body">
            <div class="service-record-toolbar">
                <t-date-range-picker v-model="searchRange" class="service-record-date-picker" :allow-input="true"
                    :clearable="false" :disable-date="disableDate" />
                <t-input v-model="keywords" class="service-record-keyword" :placeholder="t('搜索关键词')" clearable
                    @enter="handleSearch" />
                <t-select v-model="groupIds" class="service-record-select" :placeholder="t('选择客服分组')"
                    :options="groupIdsOptions" :multiple="true" :min-collapsed-num="1" :filterable="true" clearable />
                <t-button theme="primary" class="service-record-btn" @click="handleSearch">
                    {{ t('查询') }}
                </t-button>
                <t-button theme="default" variant="outline" class="service-record-btn" @click="handleReset">
                    {{ t('重置') }}
                </t-button>
            </div>

            <div class="service-record-table-wrapper">
                <t-table row-key="sessionId" :data="recordData" :columns="tableColumns" :loading="loading"
                    :bordered="false" :hover="true" :stripe="false" size="medium" vertical-align="middle"
                    table-layout="fixed" cell-empty-content="-" :max-height="tableMaxHeight" :pagination="{
                        current: searchCurrentNumber,
                        pageSize: searchPageSize,
                        total: recordTotal,
                        showJumper: true,
                        pageSizeOptions: [10, 20, 50],
                        totalContent: t('共 {count} 条', { count: recordTotal }),
                    }" @page-change="handlePageChange" />
            </div>
        </div>

        <t-drawer v-model:visible="drawerVisible" :size="'720px'" :footer="false" :close-on-overlay-click="true"
            :destroy-on-close="true" :close-btn="true" :header="drawerHeader" @close="handleDrawerClose">
            <div class="service-record-drawer-body">
                <MessageList v-if="drawerVisible" />
            </div>
        </t-drawer>

        <ChatBlacklist v-if="imBlackUserEnable" v-model:mode="blacklistDialogMode"
            :session="blacklistSession" @success="handleBlacklistSuccess" />
    </div>
</template>

<script setup lang="ts">
import { computed, h, onMounted, onUnmounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import dayjs from 'dayjs';
import type { DateValue } from 'tdesign-vue-next';
import AIDeskCoreInstance, { SESSION_TYPE, StoreName, type SessionTypeMap } from '@tencentcloud/ai-desk-core';
import ChatBlacklist from '../../Chat/ChatBlacklist/index.vue';
import MessageList from '../../../../components/MessageList/index.vue';

type BlacklistInfo = {
    startTime: number;
    endTime: number;
    blockType: number;
    reason: string;
    status: number;
};

type RecordItem = {
    sessionId: string;
    userId: string;
    userNickName: string;
    staffNickName: string;
    staffUserId: string;
    skillGroupName: string;
    channelAgentID: string;
    source: number;
    endStatus: number;
    timestamp: number;
    userBlacklist?: BlacklistInfo;
};

const { t } = useI18n();

const PEER_SOURCE: Record<string, string> = {
    '0': t('电话'),
    '1': t('内线'),
    '2': t('微信小程序'),
    '3': t('微信公众号'),
    '4': t('网页'),
    '5': t('微信公众号'),
    '6': t('微信小程序'),
    '7': t('微信客服'),
    '8': t('安卓'),
    '10': t('应用/客户端'),
    '11': 'WhatsApp',
    '12': 'Facebook Messenger',
    '13': 'Viber',
    '14': 'Telegram',
};

const IM_END_STATUS: Record<number, string> = {
    0: t('异常结束'),
    1: t('正常通话'),
    2: t('未接通'),
    3: t('无客服在线'),
    4: t('用户离线'),
    5: t('转人工前放弃'),
    6: t('座席未接入'),
    17: t('超时转接'),
    100: t('黑名单用户呼入'),
    101: t('手动转接'),
    102: t('IVR 阶段放弃'),
    103: t('用户离线'),
    104: t('座席振铃时放弃'),
    105: t('无座席在线结束'),
    106: t('非工作时间'),
    107: t('IVR 后直接结束'),
    108: t('超时自动结束'),
    109: t('用户主动结束'),
    110: t('用户超时结束'),
    111: t('客服主动结束'),
    112: t('客服超时结束'),
    113: t('机器人接待'),
    114: t('群组被解散'),
    115: t('用户被踢出群'),
    116: t('用户放弃等待接听'),
    117: t('用户放弃等待排队'),
    118: t('用户排队超时'),
    119: t('调用API结束排队'),
};

const BLACK_STATUS: Record<string, { title: string; color: string }> = {
    0: { title: t('正常'), color: '#0CBF5B' },
    1: { title: t('已拉黑'), color: '#F64041' },
    2: { title: t('即将拉黑'), color: '#FF7800' },
};

// 查询状态
const searchRange = ref<[DateValue, DateValue]>([
    dayjs().format('YYYY-MM-DD'),
    dayjs().format('YYYY-MM-DD'),
]);
const keywords = ref('');
const groupIds = ref<string[]>([]);
const groupIdsOptions = ref<{ label: string; value: string }[]>([]);
const searchCurrentNumber = ref(1);
const searchPageSize = ref(10);
const recordData = ref<RecordItem[]>([]);
const recordTotal = ref(0);
const loading = ref(false);

// 当前坐席信息
const currentUserId = ref('');
const currentSkillGroupIds = ref<string[]>([]);

// 抽屉
const drawerVisible = ref(false);
const currentSelectedSession = ref<RecordItem | null>(null);

// 表格高度（开启纵向滚动）
const tableMaxHeight = ref<string>('calc(100vh - 260px)');

// 黑名单弹窗
const blacklistDialogMode = ref<'add' | 'remove' | null>(null);
const blacklistTargetRow = ref<RecordItem | null>(null);
const imBlackUserEnable = ref(false);
const blacklistSession = computed<SessionTypeMap[SESSION_TYPE] | null>(() => {
    const row = blacklistTargetRow.value;
    if (!row) return null;
    // ChatBlacklist 只使用 session.userId / session.nickname，因此只需提供必要字段
    return {
        userId: row.userId,
        nickname: row.userNickName,
        userBlacklist: row.userBlacklist,
    } as unknown as SessionTypeMap[SESSION_TYPE];
});

const isRowBlacklisted = (row: RecordItem) => {
    const info = row?.userBlacklist;
    if (!info) return false;
    // status: 0 正常 / 1 已拉黑 / 2 即将拉黑
    return Number(info.status) === 1;
};

const handleBlacklistClick = (row: RecordItem) => {
    if (!imBlackUserEnable.value) return;
    if (!row?.userId) return;
    blacklistTargetRow.value = row;
    blacklistDialogMode.value = isRowBlacklisted(row) ? 'remove' : 'add';
};

const handleBlacklistSuccess = () => {
    blacklistDialogMode.value = null;
    blacklistTargetRow.value = null;
    // 拉黑 / 解除拉黑后重新拉取一次历史记录
    loadRecords();
};

const disableDate = {
    before: dayjs().subtract(90, 'day').format('YYYY-MM-DD'),
    after: dayjs().format('YYYY-MM-DD'),
};

const drawerHeader = computed(() => {
    const session = currentSelectedSession.value;
    if (!session) {
        return t('聊天记录');
    }
    const name = session.userNickName || session.userId || t('未知用户');
    return t('与"{name}"的聊天记录', { name });
});

const tableColumns = computed(() => [
    {
        colKey: 'timestamp',
        title: t('会话时间'),
        width: 200,
        minWidth: 200,
        cell: (_h: unknown, { row }: { row: RecordItem }) =>
            h(
                'span',
                { class: 'service-record-nowrap' },
                row.timestamp ? dayjs(row.timestamp * 1000).format('YYYY-MM-DD HH:mm:ss') : '-',
            ),
    },
    {
        colKey: 'sessionId',
        title: t('会话ID'),
        width: 180,
        ellipsis: true,
    },
    {
        colKey: 'userId',
        title: t('用户 ID'),
        width: 180,
        ellipsis: true,
    },
    {
        colKey: 'userNickName',
        title: t('用户昵称'),
        width: 140,
        ellipsis: true,
    },
    ...(imBlackUserEnable.value ? [{
        colKey: 'userBlacklistStatus',
        title: t('用户状态'),
        width: 120,
        cell: (_h: unknown, { row }: { row: RecordItem }) => {
            const status = String(row?.userBlacklist?.status ?? '0');
            const fallback = { title: t('正常'), color: '#0CBF5B' };
            const info = BLACK_STATUS[status] ?? fallback;
            return h('div', { class: 'service-record-status', style: { color: info.color } }, [
                h('span', { class: 'service-record-status-dot', style: { background: info.color } }),
                info.title,
            ]);
        },
    },
    {
        colKey: 'userBlacklistTime',
        title: t('最近拉黑持续时间'),
        width: 340,
        minWidth: 340,
        cell: (_h: unknown, { row }: { row: RecordItem }) => {
            if (row?.userBlacklist?.startTime && row?.userBlacklist?.endTime) {
                const text = `${dayjs(row.userBlacklist.startTime * 1000).format('YYYY-MM-DD HH:mm:ss')} ~ ${dayjs(
                    row.userBlacklist.endTime * 1000,
                ).format('YYYY-MM-DD HH:mm:ss')}`;
                return h('span', { class: 'service-record-nowrap' }, text);
            }
            return '-';
        },
    }] : []),
    {
        colKey: 'source',
        title: t('来源'),
        width: 140,
        cell: (_h: unknown, { row }: { row: RecordItem }) => {
            const label = row.source
                ? PEER_SOURCE[String(row.source)] || t('未知来源')
                : t('未知来源');
            return h('span', { class: 'service-record-source-tag' }, label);
        },
    },
    {
        colKey: 'staffNickName',
        title: t('客服昵称'),
        width: 140,
        ellipsis: true,
    },
    {
        colKey: 'skillGroupName',
        title: t('客服分组'),
        width: 160,
        ellipsis: true,
    },
    {
        colKey: 'endStatus',
        title: t('服务状态'),
        width: 140,
        cell: (_h: unknown, { row }: { row: RecordItem }) =>
            IM_END_STATUS[row.endStatus] || t('未知状态'),
    },
    {
        colKey: 'operation',
        title: t('操作'),
        fixed: 'right' as const,
        width: 220,
        cell: (_h: unknown, { row }: { row: RecordItem }) => {
            const blacklisted = isRowBlacklisted(row);
            return h('div', { class: 'service-record-actions' }, [
                h(
                    'span',
                    {
                        class: 'service-record-link',
                        style: { color: '#316EF5' },
                        onClick: () => handleViewChat(row),
                    },
                    t('查看聊天记录'),
                ),
                ...(imBlackUserEnable.value ? [h(
                    'span',
                    {
                        class: 'service-record-link',
                        style: { color: '#316EF5' },
                        onClick: () => handleBlacklistClick(row),
                    },
                    blacklisted ? t('解除拉黑') : t('拉黑用户'),
                )] : []),
            ]);
        },
    },
]);

const ensureFinishedSessionInStore = (row: RecordItem) => {
    const existedSession = AIDeskCoreInstance.coreStore.getSessionInfo(row.sessionId, SESSION_TYPE.IM);
    if (existedSession) {
        return;
    }
    AIDeskCoreInstance.sessionService.addRecordSession({
        sessionId: row.sessionId,
        userId: row.userId,
        avatar: '',
        nickname: row.userNickName || row.userId,
        timestamp: row.timestamp ?? Math.floor(Date.now() / 1000),
        clientData: '',
        peerSource: row.source !== undefined && row.source !== null ? String(row.source) : '0',
        channelAgentID: row.channelAgentID ?? '',
    });
};

const handleViewChat = (row: RecordItem) => {
    currentSelectedSession.value = row;
    ensureFinishedSessionInStore(row);
    AIDeskCoreInstance.sessionService.switchSession({
        sessionId: row.sessionId,
        sessionType: SESSION_TYPE.IM,
    });
    drawerVisible.value = true;
};

const handleDrawerClose = () => {
    AIDeskCoreInstance.sessionService.switchSession({ sessionId: '', sessionType: '' });
    currentSelectedSession.value = null;
};

const handleSearch = () => {
    searchCurrentNumber.value = 1;
    loadRecords();
};

const handleReset = () => {
    keywords.value = '';
    groupIds.value = [];
    searchRange.value = [dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')];
    searchCurrentNumber.value = 1;
    loadRecords();
};

const handlePageChange = (params: { current: number; pageSize: number }) => {
    const pageSizeChanged = params.pageSize !== searchPageSize.value;
    searchPageSize.value = params.pageSize;
    searchCurrentNumber.value = pageSizeChanged ? 1 : params.current;
    loadRecords();
};

const loadRecords = async () => {
    const [from, to] = searchRange.value;
    if (!from || !to) return;

    loading.value = true;
    try {
        const requestParams: any = {
            pageSize: searchPageSize.value,
            pageNumber: searchCurrentNumber.value - 1,
            fromTime: Math.floor(dayjs(from as string).startOf('day').valueOf() / 1000),
            toTime: Math.floor(dayjs(to as string).endOf('day').valueOf() / 1000),
            staffUserId: currentUserId.value,
        };
        const trimmedKeyword = keywords.value.trim();
        if (trimmedKeyword) {
            requestParams.searchPhrases = [trimmedKeyword];
        }
        if (groupIds.value.length > 0) {
            requestParams.skillGroupIds = groupIds.value.map((item) => Number(item));
        }

        const res = await AIDeskCoreInstance.sessionService.getIMSessionRecords(requestParams);
        recordData.value = (res.data ?? []) as unknown as RecordItem[];
        recordTotal.value = Number(res.totalCount) || 0;
    } catch (e) {
        console.error('getIMSessionRecords error', e);
    } finally {
        loading.value = false;
    }
};

const loadSkillGroupList = async () => {
    try {
        const res = await AIDeskCoreInstance.sessionService.getSkillGroupList({
            skillGroupType: 1,
        });
        const list = res.skillGroupList ?? [];
        const allOptions = list.map((item) => ({
            label: item.skillGroupName,
            value: String(item.skillGroupId),
        }));
        // 若已知当前坐席技能组，则过滤
        if (currentSkillGroupIds.value.length > 0) {
            groupIdsOptions.value = allOptions.filter((item) =>
                currentSkillGroupIds.value.includes(item.value),
            );
        } else {
            groupIdsOptions.value = allOptions;
        }
    } catch (e) {
        console.error('loadSkillGroupList error', e);
    }
};

const onUserIdUpdated = (userId: string) => {
    currentUserId.value = userId ?? '';
};

const onSkillGroupIdUpdated = (skillGroupIds: string[]) => {
    currentSkillGroupIds.value = Array.isArray(skillGroupIds) ? [...skillGroupIds] : [];
    // 更新过滤后的可选项
    if (groupIdsOptions.value.length > 0 && currentSkillGroupIds.value.length > 0) {
        groupIdsOptions.value = groupIdsOptions.value.filter((item) =>
            currentSkillGroupIds.value.includes(item.value),
        );
    }
};

const onImBlackUserEnableUpdated = (value: boolean) => {
    imBlackUserEnable.value = value ?? false;
    if (!imBlackUserEnable.value) {
        blacklistDialogMode.value = null;
        blacklistTargetRow.value = null;
    }
};

onMounted(async () => {
    // 初始化 userId / skillGroupId
    const initialUserId = AIDeskCoreInstance.coreStore.getData(StoreName.USERINFO, 'userId');
    if (typeof initialUserId === 'string') {
        currentUserId.value = initialUserId;
    }
    const initialSkillGroupIds = AIDeskCoreInstance.coreStore.getData(
        StoreName.USERINFO,
        'skillGroupId',
    );
    if (Array.isArray(initialSkillGroupIds)) {
        currentSkillGroupIds.value = [...initialSkillGroupIds];
    }

    AIDeskCoreInstance.coreStore.watch(StoreName.USERINFO, {
        userId: onUserIdUpdated,
        skillGroupId: onSkillGroupIdUpdated,
    });
    AIDeskCoreInstance.coreStore.watch(StoreName.APP_SETTING, {
        imBlackUserEnable: onImBlackUserEnableUpdated,
    });

    await loadSkillGroupList();
    loadRecords();
});

onUnmounted(() => {
    AIDeskCoreInstance.coreStore.unwatch(StoreName.USERINFO, {
        userId: onUserIdUpdated,
        skillGroupId: onSkillGroupIdUpdated,
    });
    AIDeskCoreInstance.coreStore.unwatch(StoreName.APP_SETTING, {
        imBlackUserEnable: onImBlackUserEnableUpdated,
    });
});
</script>

<style scoped>
.service-record {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: #fff;
    height: 100%;
    overflow: hidden;
}

.service-record-header {
    padding: 14px 16px;
    border-bottom: 1px solid #f0f0f0;
    font-size: 16px;
    font-weight: 500;
    color: #1d2129;
    flex-shrink: 0;
}

.service-record-title {
    font-size: 16px;
    font-weight: 500;
}

.service-record-body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 16px;
    gap: 12px;
    overflow: hidden;
}

.service-record-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    flex-shrink: 0;
}

.service-record-date-picker {
    width: 260px;
}

.service-record-keyword {
    width: 220px;
}

.service-record-select {
    width: 220px;
}

.service-record-btn {
    border-radius: 16px;
    min-width: 80px;
}

.service-record-table-wrapper {
    flex: 1;
    min-height: 0;
    border: 1px solid #e6e9f0;
    border-radius: 6px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.service-record-table-wrapper :deep(.t-table) {
    height: 100%;
}

.service-record-drawer-body {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    min-height: 0;
    background: #fff;
}

.service-record-drawer-body :deep(.message-list-container) {
    flex: 1;
    min-height: 0;
}
</style>

<style>
/* 非 scoped：单元格通用样式 */
.service-record-nowrap {
    white-space: nowrap;
}

.service-record-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.service-record-status-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.service-record-source-tag {
    display: inline-block;
    padding: 0 8px;
    height: 22px;
    line-height: 22px;
    border-radius: 4px;
    background: #d5e7ff;
    color: #1c66e5;
    font-size: 12px;
    font-weight: 500;
}

.service-record-link {
    color: #316EF5;
    cursor: pointer;
    font-size: 14px;
}

.service-record-link:hover {
    opacity: 0.85;
}

.service-record-link--danger {
    color: #F64041;
}

.service-record-link--normal {
    color: #0CBF5B;
}

.service-record-actions {
    display: inline-flex;
    align-items: center;
    gap: 12px;
}
</style>
