<template>
    <div class="container">
        <Breadcrumb :items="['menu.settings', 'menu.settings.xhsZlongReport']" />

        <a-row :gutter="16" class="summary-row">
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当前小时" :value="summary.hour" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-fire class="summary-icon summary-icon-request" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当日累计" :value="summary.day" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-fire class="summary-icon summary-icon-request" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当月累计" :value="summary.month" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-fire class="summary-icon summary-icon-request" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当年累计" :value="summary.year" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-fire class="summary-icon summary-icon-request" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
        </a-row>
        <a-row :gutter="16" class="summary-row">
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当前小时异常" :value="summary.hour_exception" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-exclamation-circle class="summary-icon summary-icon-exception" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当日异常" :value="summary.day_exception" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-exclamation-circle class="summary-icon summary-icon-exception" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当月异常" :value="summary.month_exception" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-exclamation-circle class="summary-icon summary-icon-exception" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
            <a-col :span="6">
                <a-card class="summary-card">
                    <a-statistic title="当年异常" :value="summary.year_exception" :value-from="0" animation show-group-separator>
                        <template #prefix><icon-exclamation-circle class="summary-icon summary-icon-exception" /></template>
                    </a-statistic>
                </a-card>
            </a-col>
        </a-row>

        <a-card class="general-card" :title="$t('menu.settings.xhsZlongReport')">
            <a-row>
                <a-col :flex="1">
                    <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
                        label-align="left">
                        <a-row :gutter="16">
                            <a-col :span="6">
                                <a-form-item field="channels" label="渠道">
                                    <a-select v-model="formModel.channels" multiple allow-clear placeholder="全部渠道"
                                        @change="search">
                                        <a-option v-for="item in channelOptions" :key="item.value" :value="item.value">
                                            {{ item.label }}
                                        </a-option>
                                    </a-select>
                                </a-form-item>
                            </a-col>
                            <a-col :span="6">
                                <a-form-item field="bucket_type" label="统计粒度">
                                    <a-select v-model="formModel.bucket_type" @change="search">
                                        <a-option value="hour">小时</a-option>
                                        <a-option value="day">日</a-option>
                                        <a-option value="month">月</a-option>
                                        <a-option value="year">年</a-option>
                                    </a-select>
                                </a-form-item>
                            </a-col>
                            <a-col :span="10">
                                <a-form-item field="dateRange" label="时间范围">
                                    <a-range-picker v-model="dateRange" value-format="YYYY-MM-DD" style="width: 100%"
                                        allow-clear @change="search" />
                                </a-form-item>
                            </a-col>
                        </a-row>
                    </a-form>
                </a-col>
                <a-divider style="height: 38px" direction="vertical" />
                <a-col :flex="'86px'" style="text-align: right">
                    <a-space direction="vertical" :size="18">
                        <a-button type="primary" @click="search">
                            <template #icon>
                                <icon-search />
                            </template>
                            查询
                        </a-button>
                    </a-space>
                </a-col>
            </a-row>

            <div class="trend-panel">
                <div class="trend-header">
                    <span class="trend-title">趋势图</span>
                    <a-space :size="16">
                        <span class="trend-legend">
                            <i class="trend-dot trend-dot-request"></i>
                            请求数
                        </span>
                        <span class="trend-legend">
                            <i class="trend-dot trend-dot-exception"></i>
                            异常数
                        </span>
                    </a-space>
                </div>
                <Chart height="320px" :option="chartOption" />
            </div>

            <a-row style="margin-bottom: 16px">
                <a-col :span="12"></a-col>
                <a-col :span="12" style="display: flex; align-items: center; justify-content: end;">
                    <a-tooltip :content="$t('searchTable.actions.refresh')">
                        <div class="action-icon" @click="refresh"><icon-refresh size="18" /></div>
                    </a-tooltip>
                </a-col>
            </a-row>

            <a-table row-key="redis_key" :loading="loading" :pagination="pagination" :columns="columns"
                :data="renderData" :bordered="{ headerCell: true }" size="small" @page-change="onPageChange"
                @page-size-change="onPageSizeChange">
                <template #channel="{ record }">
                    <a-tag :color="channelColorMap[record.channel] || 'gray'">
                        {{ channelLabelMap[record.channel] || record.channel }}
                    </a-tag>
                </template>
                <template #bucket_type="{ record }">
                    <a-tag :color="bucketColorMap[record.bucket_type] || 'gray'">
                        {{ bucketLabelMap[record.bucket_type] || record.bucket_type }}
                    </a-tag>
                </template>
                <template #total="{ record }">
                    <a-tag color="arcoblue">{{ Number(record.total || 0).toLocaleString() }}</a-tag>
                </template>
                <template #exception_count="{ record }">
                    <a-tag color="orangered">{{ Number(record.exception_count || 0).toLocaleString() }}</a-tag>
                </template>
            </a-table>
        </a-card>
    </div>
</template>

<script lang="ts" setup>
import { computed, onMounted, reactive, ref } from 'vue';
import dayjs from 'dayjs';
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
import useLoading from '@/hooks/loading';
import useChartOption from '@/hooks/chart-option';
import type { Pagination } from '@/types/global';
import {
    queryXhsZlongForwardReport,
    type XhsZlongForwardReportParams,
    type XhsZlongForwardReportRecord,
    type XhsZlongForwardReportSummary,
} from '@/api/taobao';
import {
    zlongForwardChannelColorMap as channelColorMap,
    zlongForwardChannelLabelMap as channelLabelMap,
    zlongForwardChannelOptions as channelOptions,
    zlongForwardChannelValues,
    normalizeZlongForwardChannels,
} from './zlongForwardChannels';

const bucketLabelMap: Record<string, string> = {
    hour: '小时',
    day: '日',
    month: '月',
    year: '年',
};
const bucketColorMap: Record<string, string> = {
    hour: 'blue',
    day: 'green',
    month: 'orange',
    year: 'purple',
};

const { loading, setLoading } = useLoading(false);
const renderData = ref<XhsZlongForwardReportRecord[]>([]);
const chartData = ref<XhsZlongForwardReportRecord[]>([]);
const summary = ref<XhsZlongForwardReportSummary>({
    hour: 0,
    day: 0,
    month: 0,
    year: 0,
    hour_exception: 0,
    day_exception: 0,
    month_exception: 0,
    year_exception: 0,
});

const formModel = reactive({
    channels: [...zlongForwardChannelValues],
    bucket_type: 'day',
});

const dateRange = ref<string[]>([
    dayjs().subtract(30, 'day').format('YYYY-MM-DD'),
    dayjs().format('YYYY-MM-DD'),
]);

const basePagination: Pagination = {
    current: 1,
    pageSize: 20,
    total: 0,
    showPageSize: true,
    showTotal: true,
    pageSizeOptions: [20, 50, 100],
};
const pagination = reactive({
    ...basePagination,
});

const toNumber = (value: unknown) => Number(value || 0);
const normalizeChannels = (channels?: string[]) => {
    const list = normalizeZlongForwardChannels(channels);
    return list.length > 0 ? list : [...zlongForwardChannelValues];
};
const buildChannelsValue = (channels?: string[]) => normalizeChannels(channels).join(',');
const normalizeRecord = (item: XhsZlongForwardReportRecord): XhsZlongForwardReportRecord => ({
    ...item,
    channel: String(item.channel || '').toLowerCase(),
    total: toNumber(item.total),
    exception_count: toNumber(item.exception_count),
});
const sortedChartData = computed(() => {
    const grouped = new Map<string, XhsZlongForwardReportRecord>();

    chartData.value.forEach((item) => {
        const key = String(item.report_time || item.display_time || '');
        const current = grouped.get(key);

        if (current) {
            current.total += toNumber(item.total);
            current.exception_count += toNumber(item.exception_count);
            return;
        }

        grouped.set(key, {
            ...item,
            total: toNumber(item.total),
            exception_count: toNumber(item.exception_count),
        });
    });

    return Array.from(grouped.values()).sort((left, right) => {
        return new Date(left.report_time).getTime() - new Date(right.report_time).getTime();
    });
});
const chartXAxis = computed(() => sortedChartData.value.map((item) => item.display_time));
const chartTotalSeries = computed(() => sortedChartData.value.map((item) => item.total));
const chartExceptionSeries = computed(() => sortedChartData.value.map((item) => item.exception_count));
const chartLabelInterval = computed(() => {
    const count = chartXAxis.value.length;
    if (count <= 12) return 0;
    return Math.ceil(count / 12) - 1;
});
const { chartOption } = useChartOption(() => ({
    grid: {
        left: 48,
        right: 24,
        top: 48,
        bottom: 48,
    },
    tooltip: {
        trigger: 'axis',
        className: 'echarts-tooltip-diy',
        formatter(params: any) {
            const lines = (params || []).map((item: any) => {
                return `<div class="content-panel"><span>${item.seriesName}</span><span class="tooltip-value">${Number(item.value || 0).toLocaleString()}</span></div>`;
            });
            const axisLabel = params?.[0]?.axisValueLabel || '';
            return `<div><p class="tooltip-title">${axisLabel}</p>${lines.join('')}</div>`;
        },
    },
    legend: {
        show: false,
    },
    xAxis: {
        type: 'category',
        boundaryGap: false,
        data: chartXAxis.value,
        axisLabel: {
            interval: chartLabelInterval.value,
            rotate: chartXAxis.value.length > 10 ? 25 : 0,
            color: '#4E5969',
        },
        axisLine: {
            lineStyle: {
                color: '#E5E8EF',
            },
        },
    },
    yAxis: {
        type: 'value',
        axisLabel: {
            color: '#4E5969',
        },
        splitLine: {
            lineStyle: {
                type: 'dashed',
                color: '#E5E8EF',
            },
        },
    },
    series: [
        {
            name: '请求数',
            type: 'line',
            smooth: true,
            showSymbol: false,
            symbolSize: 8,
            data: chartTotalSeries.value,
            lineStyle: {
                width: 3,
                color: '#165DFF',
            },
            itemStyle: {
                color: '#165DFF',
            },
            areaStyle: {
                color: 'rgba(22, 93, 255, 0.12)',
            },
        },
        {
            name: '异常数',
            type: 'line',
            smooth: true,
            showSymbol: false,
            symbolSize: 8,
            data: chartExceptionSeries.value,
            lineStyle: {
                width: 3,
                color: '#F53F3F',
            },
            itemStyle: {
                color: '#F53F3F',
            },
            areaStyle: {
                color: 'rgba(245, 63, 63, 0.08)',
            },
        },
    ],
}));

const columns = computed<TableColumnData[]>(() => [
    {
        title: '渠道',
        slotName: 'channel',
        width: 110,
    },
    {
        title: '统计粒度',
        slotName: 'bucket_type',
        width: 100,
    },
    {
        title: '统计时间',
        dataIndex: 'display_time',
        width: 180,
    },
    {
        title: '请求数',
        slotName: 'total',
        width: 120,
    },
    {
        title: '异常数',
        slotName: 'exception_count',
        width: 120,
    },
]);

const buildParams = (current = 1, pageSize = pagination.pageSize): XhsZlongForwardReportParams => {
    return {
        current,
        pageSize,
        channels: buildChannelsValue(formModel.channels),
        bucket_type: formModel.bucket_type,
        start: dateRange.value?.[0] || undefined,
        end: dateRange.value?.[1] || undefined,
        getTotal: true,
    };
};

const buildChartParams = (): XhsZlongForwardReportParams => {
    return {
        ...buildParams(1, formModel.bucket_type === 'hour' ? 10000 : 2000),
        getTotal: false,
    };
};

const fetchTableData = async (params: XhsZlongForwardReportParams) => {
    const res: any = await queryXhsZlongForwardReport(params);
    if (!res?.data) return;

    renderData.value = (res.data.list || []).map(normalizeRecord);
    summary.value = {
        hour: toNumber(res.data.summary?.hour),
        day: toNumber(res.data.summary?.day),
        month: toNumber(res.data.summary?.month),
        year: toNumber(res.data.summary?.year),
        hour_exception: toNumber(res.data.summary?.hour_exception),
        day_exception: toNumber(res.data.summary?.day_exception),
        month_exception: toNumber(res.data.summary?.month_exception),
        year_exception: toNumber(res.data.summary?.year_exception),
    };
    pagination.current = res.data.page || 1;
    pagination.pageSize = res.data.size || pagination.pageSize;
    pagination.total = res.data.count || 0;
};

const fetchChartData = async () => {
    const res: any = await queryXhsZlongForwardReport(buildChartParams());
    if (!res?.data) {
        chartData.value = [];
        return;
    }

    chartData.value = (res.data.list || []).map(normalizeRecord);
};

const loadReport = async (current = 1, pageSize = pagination.pageSize) => {
    setLoading(true);
    try {
        await Promise.all([
            fetchTableData(buildParams(current, pageSize)),
            fetchChartData(),
        ]);
    } catch (err) {
        console.error(err);
    } finally {
        setLoading(false);
    }
};

const search = () => {
    loadReport(1, pagination.pageSize);
};

const refresh = () => {
    loadReport(pagination.current, pagination.pageSize);
};

const onPageChange = async (current: number) => {
    setLoading(true);
    try {
        await fetchTableData(buildParams(current, pagination.pageSize));
    } catch (err) {
        console.error(err);
    } finally {
        setLoading(false);
    }
};

const onPageSizeChange = (pageSize: number) => {
    pagination.pageSize = pageSize;
    loadReport(1, pageSize);
};

onMounted(() => {
    search();
});
</script>

<script lang="ts">
export default {
    name: 'XhsZlongReport',
};
</script>

<style scoped lang="less">
.container {
    padding: 0 20px 20px 20px;
}

.summary-row {
    margin-bottom: 16px;
}

.summary-card {
    height: 100%;
}

.summary-icon {
    margin-right: 8px;
    font-size: 16px;
}

.summary-icon-request {
    color: rgb(var(--arcoblue-6));
}

.summary-icon-exception {
    color: rgb(var(--orangered-6));
}

.trend-panel {
    margin-bottom: 16px;
    padding: 20px 20px 8px;
    border-radius: 12px;
    background: linear-gradient(180deg, var(--color-fill-1), var(--color-bg-1));
}

.trend-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

.trend-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--color-text-1);
}

.trend-legend {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--color-text-2);
}

.trend-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
}

.trend-dot-request {
    background: #165dff;
}

.trend-dot-exception {
    background: #f53f3f;
}

.report-alert {
    margin-bottom: 16px;
}

:deep(.general-card) {
    height: 100%;
}
</style>
