<template>
    <div class="default-main">
        <el-alert type="info" :title="tip" show-icon class="mb-12" />
        <el-alert :type="connected ? 'success' : 'warning'" :title="connected ? t('test.push.connected') : t('test.push.disconnected')" show-icon class="mb-12" />

        <el-card shadow="never" class="mb-12">
            <el-form :inline="true" @submit.prevent>
                <el-form-item v-if="useUuid" :label="t('test.push.user_uuid')">
                    <el-input v-model="userUuid" :placeholder="t('test.push.user_uuid_placeholder')" clearable style="width: 280px" />
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" :loading="loading" @click="connect">{{ t('test.push.btn_connect') }}</el-button>
                    <el-button :disabled="!session" @click="disconnect">{{ t('test.push.btn_disconnect') }}</el-button>
                    <el-button @click="clearLogs">{{ t('test.push.btn_clear') }}</el-button>
                </el-form-item>
            </el-form>
            <div class="text-muted mb-8">{{ t('test.push.channel_label') }}: {{ channelName || '-' }}</div>
        </el-card>

        <el-card shadow="never">
            <template #header>{{ t('test.push.log_title') }}</template>
            <el-scrollbar max-height="480">
                <pre class="push-log">{{ logText }}</pre>
            </el-scrollbar>
        </el-card>
    </div>
</template>

<script setup lang="ts">
import { computed, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import createAxios from '/@/utils/axios'
import { loadPushJs, startPushChannelListener, type PushTestLogLine } from '/@/utils/backend/pushChannelTest'

const props = withDefaults(
    defineProps<{
        /** 如 /admin/test.PushGamePeriod/pushConfig */
        configApi: string
        useUuid?: boolean
        tip: string
    }>(),
    {
        useUuid: false,
    }
)

const { t } = useI18n()
const loading = ref(false)
const connected = ref(false)
const channelName = ref('')
const userUuid = ref('')
const logs = ref<PushTestLogLine[]>([])
const session = ref<{ disconnect: () => void } | null>(null)

const logText = computed(() => {
    if (!logs.value.length) return t('test.push.log_empty')
    return logs.value
        .map((row) => {
            const time = new Date(row.t).toLocaleString()
            return `[${time}] ${row.event}\n${row.payload}`
        })
        .join('\n\n')
})

function appendLog(line: PushTestLogLine) {
    logs.value = [line, ...logs.value].slice(0, 200)
}

function clearLogs() {
    logs.value = []
}

async function connect() {
    if (props.useUuid && !userUuid.value.trim()) {
        return
    }
    loading.value = true
    disconnect()
    try {
        await loadPushJs()
        const params: anyObj = {}
        if (props.useUuid) {
            params.uuid = userUuid.value.trim()
        }
        const res = await createAxios({
            url: props.configApi,
            method: 'get',
            params,
            showCodeMessage: true,
        })
        if (res.code !== 1 || !res.data) {
            connected.value = false
            return
        }
        const { url, app_key, channel } = res.data
        channelName.value = typeof channel === 'string' ? channel : ''
        try {
            const handle = startPushChannelListener({
                url,
                app_key,
                channel: channelName.value,
                usePrivateAuth: !!props.useUuid,
                onLog: appendLog,
                onConnected: (ok) => {
                    connected.value = ok
                },
            })
            session.value = handle
        } catch {
            connected.value = false
        }
    } finally {
        loading.value = false
    }
}

function disconnect() {
    if (session.value) {
        session.value.disconnect()
        session.value = null
    }
    connected.value = false
}

onUnmounted(() => {
    disconnect()
})
</script>

<style scoped>
.push-log {
    margin: 0;
    font-size: 12px;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-all;
}
.text-muted {
    color: var(--el-text-color-secondary);
    font-size: 13px;
}
</style>
