<script lang="ts">
export default { name: "DashboardDailyPnl" };
</script>

<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, reactive, computed, watch } from "vue";
import { useRouter } from "vue-router";
import { init, EChartsOption } from "echarts";
import resize from "@/utils/resize";
import { dailyPnl, dailyPnlBackfill } from "@/api/system/dashboard";
import { ElMessage } from "element-plus";

const router = useRouter();

const props = defineProps<{
    includeInternal?: number;
    type?: "self" | "copy" | "all";
}>();

interface DayRow {
    stat_date:               string;
    self_today_close_profit: number;
    self_today_close_loss:   number;
    self_diff:               number;
    copy_today_close_profit: number;
    copy_today_close_loss:   number;
    copy_diff:               number;
    total_profit:            number;
    total_loss:              number;
    diff:                    number;
}

const state = reactive({
    loading: false,
    syncing: false,
    days:    7 as 7 | 30,
    rows:    [] as DayRow[],
});

const { mounted: resizeMounted, chart, beforeDestroy } = resize();

const activeType = computed(() => props.type ?? "all");

const profitKey = computed(() => {
    if (activeType.value === "self") return "self_today_close_profit";
    if (activeType.value === "copy") return "copy_today_close_profit";
    return "total_profit";
});
const lossKey = computed(() => {
    if (activeType.value === "self") return "self_today_close_loss";
    if (activeType.value === "copy") return "copy_today_close_loss";
    return "total_loss";
});
const diffKey = computed(() => {
    if (activeType.value === "self") return "self_diff";
    if (activeType.value === "copy") return "copy_diff";
    return "diff";
});

watch(() => props.includeInternal, () => load());
watch(() => props.type, () => renderChart());

async function load(days: 7 | 30 = state.days) {
    state.loading = true;
    try {
        const res: any = await dailyPnl(days, (props.includeInternal ?? 0) as 0 | 1);
        state.rows = (res?.data ?? []).map((r: any) => ({
            stat_date:               r.stat_date,
            self_today_close_profit: Number(r.self_today_close_profit) || 0,
            self_today_close_loss:   Number(r.self_today_close_loss)   || 0,
            self_diff:               Number(r.self_diff)               || 0,
            copy_today_close_profit: Number(r.copy_today_close_profit) || 0,
            copy_today_close_loss:   Number(r.copy_today_close_loss)   || 0,
            copy_diff:               Number(r.copy_diff)               || 0,
            total_profit:            Number(r.total_profit)            || 0,
            total_loss:              Number(r.total_loss)              || 0,
            diff:                    Number(r.diff)                    || 0,
        }));
        await nextTick();
        renderChart();
    } catch (e) {
        console.error("[DailyPnl]", e);
    } finally {
        state.loading = false;
    }
}

function setDays(days: 7 | 30) {
    state.days = days;
    load(days);
}

async function handleSync() {
    state.syncing = true;
    try {
        await dailyPnlBackfill(30);
        ElMessage.success("历史数据同步完成");
        await load(state.days);
    } catch (e) {
        ElMessage.error("同步失败，请稍后重试");
    } finally {
        state.syncing = false;
    }
}

function fmtDate(d: string) {
    const parts = d.split("-");
    if (parts.length < 3) return d;
    return parseInt(parts[1]) + "月" + parseInt(parts[2]) + "日";
}

function fmt(v: number, dec = 2) {
    return Number(v).toLocaleString("en-US", {
        minimumFractionDigits: dec,
        maximumFractionDigits: dec,
    });
}

function diffClass(v: number) {
    if (v > 0) return "is-loss";
    if (v < 0) return "is-profit";
    return "";
}

function renderChart() {
    const el = document.getElementById("dailyPnlChart");
    if (!el) return;
    if (!chart.value) chart.value = init(el);

    const dates   = state.rows.map(r => fmtDate(r.stat_date));
    const profits = state.rows.map(r => (r as any)[profitKey.value]);
    const losses  = state.rows.map(r => (r as any)[lossKey.value]);
    const diffs   = state.rows.map(r => (r as any)[diffKey.value]);

    const opts: EChartsOption = {
        color: ["#409eff", "#e6735c", "#f0c040"],
        tooltip: {
            trigger: "axis",
            axisPointer: { type: "shadow" },
            formatter(params: any) {
                let s = params[0].name + "<br/>";
                params.forEach((p: any) => {
                    s += p.marker + p.seriesName + ": " + fmt(p.value) + "<br/>";
                });
                return s;
            },
        },
        legend: {
            data: ["盈利", "亏损", "差额"],
            top: 4,
            textStyle: { fontSize: 12 },
            selectedMode: false,
        },
        grid: {
            top: 36,
            bottom: 24,
            left: 12,
            right: 12,
            containLabel: true,
        },
        xAxis: {
            type: "category",
            data: dates,
            axisLabel: { fontSize: 11 },
            axisTick: { show: false },
            axisLine: { lineStyle: { color: "#ddd" } },
        },
        yAxis: {
            type: "value",
            axisLabel: {
                fontSize: 11,
                formatter: (v: number) =>
                    v >= 1e6 ? (v / 1e6).toFixed(1) + "M"
                    : v >= 1e3 ? (v / 1e3).toFixed(0) + "K"
                    : String(v),
            },
            splitLine: { lineStyle: { color: "#f5f5f5" } },
        },
        series: [
            {
                name: "盈利",
                type: "bar",
                data: profits,
                barMaxWidth: 20,
                itemStyle: { borderRadius: [3, 3, 0, 0] },
            },
            {
                name: "亏损",
                type: "bar",
                data: losses,
                barMaxWidth: 20,
                itemStyle: { borderRadius: [3, 3, 0, 0] },
            },
            {
                name: "差额",
                type: "bar",
                data: diffs,
                barMaxWidth: 14,
                itemStyle: { borderRadius: [3, 3, 0, 0] },
            },
        ],
    };
    chart.value.setOption(opts, true);
}

onBeforeUnmount(() => { beforeDestroy(); });

onMounted(() => {
    resizeMounted();
    load();
});
</script>

<template>
    <div class="daily-pnl-section" v-loading="state.loading" element-loading-text="加载中...">
        <div class="section-header">
            <span class="section-title">每日盈亏统计表</span>
            <div class="header-actions">
                <el-button
                    size="small"
                    :type="state.days === 7 ? 'primary' : ''"
                    @click="setDays(7)"
                >最近7日</el-button>
                <el-button
                    size="small"
                    :type="state.days === 30 ? 'primary' : ''"
                    @click="setDays(30)"
                >最近30日</el-button>
                <el-button
                    size="small"
                    :loading="state.syncing"
                    @click="handleSync"
                >同步历史数据</el-button>
                <el-button
                    size="small"
                    type="default"
                    @click="router.push('/platform-pnl')"
                >查看明细</el-button>
            </div>
        </div>

        <div id="dailyPnlChart" style="height: 280px; width: 100%" />

        <div class="table-scroll" v-if="state.rows.length > 0">
            <table class="data-table">
                <thead>
                    <tr>
                        <th class="label-th"></th>
                        <th v-for="row in state.rows" :key="row.stat_date">
                            {{ fmtDate(row.stat_date) }}
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td class="label-td">
                            <span class="dot" style="background:#409eff" />盈利
                        </td>
                        <td v-for="row in state.rows" :key="row.stat_date" class="is-profit">
                            {{ fmt((row as any)[profitKey]) }}
                        </td>
                    </tr>
                    <tr>
                        <td class="label-td">
                            <span class="dot" style="background:#e6735c" />亏损
                        </td>
                        <td v-for="row in state.rows" :key="row.stat_date" class="is-loss">
                            {{ fmt((row as any)[lossKey]) }}
                        </td>
                    </tr>
                    <tr>
                        <td class="label-td">
                            <span class="dot" style="background:#f0c040" />差额
                        </td>
                        <td
                            v-for="row in state.rows"
                            :key="row.stat_date"
                            :class="diffClass((row as any)[diffKey])"
                        >
                            {{ fmt((row as any)[diffKey]) }}
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
        <el-empty v-else-if="!state.loading" description="暂无数据" :image-size="60" style="padding: 20px 0" />
    </div>
</template>

<style lang="scss" scoped>
.daily-pnl-section {
    padding: 16px 20px;
}

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

    .section-title {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
    }

    .header-actions {
        display: flex;
        gap: 8px;
    }
}

.table-scroll {
    margin-top: 12px;
    overflow-x: auto;
}

.data-table {
    border-collapse: collapse;
    width: 100%;
    min-width: max-content;
    font-size: 12px;

    th, td {
        padding: 6px 10px;
        text-align: center;
        border: 1px solid #ebeef5;
        white-space: nowrap;
    }

    th {
        background: #f5f7fa;
        color: #606266;
        font-weight: 600;
    }

    .label-th, .label-td {
        text-align: left;
        min-width: 64px;
        background: #fafafa;
        font-weight: 600;
        color: #303133;
    }
}

.dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    margin-right: 5px;
    vertical-align: middle;
}

.is-profit { color: #67c23a; }
.is-loss   { color: #f56c6c; }
</style>
