<!--  合约持仓图表：当前持仓多空占比 / 当前持仓分布 -->
<script lang="ts">
export default { name: "DashboardInventoryChart" };
</script>

<script setup lang="ts">
import {
    nextTick,
    onActivated,
    onBeforeUnmount,
    onDeactivated,
    onMounted,
    reactive,
    watch,
} from "vue";
import { init, EChartsOption } from "echarts";
import resize from "@/utils/resize";
import { queryContractCoinList } from "@/api/system/dashboard";

interface Row {
    symbol:      string;
    buy:         number;
    sell:        number;
    buyValue:    number; // 多头 USDT 价值 = buy * price
    sellValue:   number; // 空头 USDT 价值 = sell * price
    buyPct:      number;
    sellPct:     number;
    value:       number; // buyValue + sellValue，用于排序和饼图
}

const props = defineProps({
    id:        { type: String, default: "inventoryChart" },
    className: { type: String, default: "" },
    width:     { type: String, default: "100%", required: true },
    height:    { type: String, default: "420px", required: true },
    type:      { type: String as () => "self" | "copy", default: "self" },
});

const state = reactive({
    activeTab: "ratio" as "ratio" | "dist",
    allRows:   [] as Row[],                             // [总持仓量, sym1…symN, 其他?]
    pieRows:   [] as { name: string; value: number }[], // top symbols for donut
});

const { mounted, chart, beforeDestroy, activated, deactivated } = resize();

watch(() => props.type, () => { loadAndRender(); });

// ── 数据加载 ──────────────────────────────────────────────────────────────────

const TOP_N = 5;

function loadAndRender() {
    queryContractCoinList({ pageNo: 1, pageSize: 1000, positionType: props.type })
        .then(({ data }: any) => {
            const coins: Row[] = [];
            (data.content ?? []).forEach((coin: any) => {
                if (coin.enable !== 1) return;
                const buy       = Number(coin.buyPosition)  || 0;
                const sell      = Number(coin.sellPosition) || 0;
                if (buy <= 0 && sell <= 0) return;
                const price     = Number(coin.currentPrice) || 0;
                const buyValue  = round2(buy  * price);
                const sellValue = round2(sell * price);
                const value     = buyValue + sellValue;
                coins.push({ symbol: coin.symbol, buy, sell, buyValue, sellValue, buyPct: 0, sellPct: 0, value });
            });

            // 按持仓 USDT 价值降序
            coins.sort((a, b) => b.value - a.value);

            // Top N + 其他
            let rows: Row[];
            if (coins.length <= TOP_N) {
                rows = [...coins];
            } else {
                rows = coins.slice(0, TOP_N);
                const otherBuyVal  = round2(coins.slice(TOP_N).reduce((s, c) => s + c.buyValue,  0));
                const otherSellVal = round2(coins.slice(TOP_N).reduce((s, c) => s + c.sellValue, 0));
                const otherBuy     = round2(coins.slice(TOP_N).reduce((s, c) => s + c.buy,       0));
                const otherSell    = round2(coins.slice(TOP_N).reduce((s, c) => s + c.sell,      0));
                rows.push({ symbol: "其他", buy: otherBuy, sell: otherSell, buyValue: otherBuyVal, sellValue: otherSellVal, buyPct: 0, sellPct: 0, value: round2(otherBuyVal + otherSellVal) });
            }

            // 合计行
            const totalBuyVal  = round2(coins.reduce((s, c) => s + c.buyValue,  0));
            const totalSellVal = round2(coins.reduce((s, c) => s + c.sellValue, 0));
            const totalBuy     = round2(coins.reduce((s, c) => s + c.buy,       0));
            const totalSell    = round2(coins.reduce((s, c) => s + c.sell,      0));
            const totalRow: Row = { symbol: "总持仓量", buy: totalBuy, sell: totalSell, buyValue: totalBuyVal, sellValue: totalSellVal, buyPct: 0, sellPct: 0, value: round2(totalBuyVal + totalSellVal) };

            // 百分比基于 USDT 价值（跨币种时有意义）
            [totalRow, ...rows].forEach(r => {
                const t = r.buyValue + r.sellValue;
                r.buyPct  = t > 0 ? +(r.buyValue  / t * 100).toFixed(1) : 0;
                r.sellPct = t > 0 ? +(r.sellValue / t * 100).toFixed(1) : 0;
            });

            state.allRows = [totalRow, ...rows];

            // 饼图：top5 + 其他（按持仓价值）
            const pieOtherValue = round2(coins.slice(TOP_N).reduce((s, c) => s + c.value, 0));
            state.pieRows = [
                ...coins.slice(0, TOP_N).map(c => ({ name: c.symbol, value: round2(c.value) })),
                ...(pieOtherValue > 0 ? [{ name: "其他", value: pieOtherValue }] : []),
            ];
        })
        .then(() => { renderChart(); })
        .catch(err => { console.error("[InventoryChart]", err); });
}

// ── 图表渲染 ──────────────────────────────────────────────────────────────────

function renderChart() {
    const el = document.getElementById(props.id);
    if (!el) return;
    if (!chart.value) chart.value = init(el);
    const opts = state.activeTab === "ratio" ? getRatioOptions() : getDistOptions();
    chart.value.setOption(opts as EChartsOption, true);
}

function switchTab(tab: "ratio" | "dist") {
    state.activeTab = tab;
    renderChart();
}

// ── 多空占比图 ─────────────────────────────────────────────────────────────────

function getRatioOptions(): EChartsOption {
    const rows    = state.allRows;
    const symbols = rows.map(r => r.symbol);
    const pctBuy  = rows.map(r => r.buyPct);
    const pctSell = rows.map(r => r.sellPct);

    return {
        tooltip: {
            trigger: "axis",
            axisPointer: { type: "none" },
            formatter: (params: any) => {
                const r = rows[params[0].dataIndex];
                return (
                    `<b>${r.symbol}</b><br/>` +
                    `<span style="color:#3bbf88">●</span> 多头: ${fmt(r.buyValue)} USDT (${r.buyPct}%)<br/>` +
                    `<span style="color:#f56c6c">●</span> 空头: ${fmt(r.sellValue)} USDT (${r.sellPct}%)`
                );
            },
        },
        legend: {
            data: ["多头", "空头"],
            bottom: 0,
            itemWidth: 12, itemHeight: 12,
            textStyle: { fontSize: 12, color: "#606266" },
        },
        grid: { top: 8, bottom: 36, left: 8, right: 78, containLabel: true },
        xAxis: { type: "value", show: false, min: 0, max: 100 },
        yAxis: {
            type: "category",
            inverse: true,
            data: symbols,
            axisTick: { show: false },
            axisLine: { show: false },
            axisLabel: {
                fontSize: 12,
                color: "#303133",
                rich: { bold: { fontWeight: "bold", fontSize: 13, color: "#303133" } },
                formatter: (v: string) => v === "总持仓量" ? "{bold|" + v + "}" : v,
            },
        },
        series: [
            {
                name: "多头",
                type: "bar",
                stack: "pos",
                barWidth: 28,
                itemStyle: { color: "#3bbf88", borderRadius: [3, 0, 0, 3] },
                // 多头：占比 >= 6% 显示在内部；< 6% 且 > 0 则在左侧外部（反向）
                data: pctBuy.map((pct, i) => ({
                    value: pct,
                    label: pct <= 0 ? { show: false } : pct >= 6 ? {
                        show: true, position: "inside",
                        color: "#fff", fontSize: 11, fontWeight: "bold",
                        formatter: () => `${fmt(rows[i].buyValue)}  (${pct}%)`,
                    } : {
                        show: true, position: "insideLeft",
                        color: "#3bbf88", fontSize: 11, fontWeight: "bold",
                        offset: [-4, 0],
                        formatter: () => `${fmt(rows[i].buyValue)} (${pct}%)`,
                    },
                })),
            },
            {
                name: "空头",
                type: "bar",
                stack: "pos",
                barWidth: 28,
                itemStyle: { color: "#f56c6c", borderRadius: [0, 3, 3, 0] },
                // 空头：占比 >= 10% 显示在内部；0 < pct < 10% 则在条形右侧外部
                data: pctSell.map((pct, i) => ({
                    value: pct,
                    label: pct <= 0 ? { show: false } : pct >= 10 ? {
                        show: true, position: "inside",
                        color: "#fff", fontSize: 11, fontWeight: "bold",
                        formatter: () => `${fmt(rows[i].sellValue)}  (${pct}%)`,
                    } : {
                        show: true, position: "right",
                        color: "#f56c6c", fontSize: 11, fontWeight: "bold",
                        formatter: () => `${fmt(rows[i].sellValue)} (${pct}%)`,
                    },
                })),
            },
        ],
    };
}

// ── 持仓分布饼图 ───────────────────────────────────────────────────────────────

function getDistOptions(): EChartsOption {
    const data  = state.pieRows;
    const total = data.reduce((s, d) => s + d.value, 0);

    return {
        tooltip: {
            trigger: "item",
            formatter: (p: any) => `${p.name}<br/>${fmt(p.value)} (${p.percent}%)`,
        },
        legend: {
            orient: "vertical",
            right: 16,
            top: "middle",
            itemWidth: 10, itemHeight: 10,
            textStyle: { fontSize: 12, color: "#606266" },
            formatter: (name: string) => {
                const item = data.find(d => d.name === name);
                if (!item || total === 0) return name;
                const pct = (item.value / total * 100).toFixed(1);
                return `${name}   ${pct}%`;
            },
        },
        series: [
            {
                name: "当前持仓分布",
                type: "pie",
                radius: ["38%", "66%"],
                center: ["36%", "50%"],
                avoidLabelOverlap: true,
                label: {
                    show: true,
                    formatter: "{b}\n{d}%",
                    fontSize: 11,
                    color: "#606266",
                    lineHeight: 18,
                },
                labelLine: { length: 8, length2: 10 },
                emphasis: {
                    label: { show: true, fontSize: 13, fontWeight: "bold" },
                },
                data,
            },
        ],
    };
}

// ── 工具函数 ──────────────────────────────────────────────────────────────────

function round2(v: number) { return Math.round(v * 100) / 100; }
function fmt(v: number)    { return v.toLocaleString("en-US", { maximumFractionDigits: 2 }); }

// ── 生命周期 ──────────────────────────────────────────────────────────────────

onBeforeUnmount(() => { beforeDestroy(); });
onActivated(()    => { activated(); });
onDeactivated(()  => { deactivated(); });
defineExpose({ reload: loadAndRender });

onMounted(() => {
    mounted();
    nextTick(() => { loadAndRender(); });
});
</script>

<template>
    <div class="inventory-card">
        <!-- Tab 栏 -->
        <div class="tab-bar">
            <span
                :class="['tab-item', state.activeTab === 'ratio' ? 'active' : '']"
                @click="switchTab('ratio')"
            >当前持仓多空占比</span>
            <span
                :class="['tab-item', state.activeTab === 'dist' ? 'active' : '']"
                @click="switchTab('dist')"
            >当前持仓分布</span>
        </div>

        <!-- ECharts 画布 -->
        <div :id="id" :class="className" :style="{ height: 'calc(' + height + ' - 48px)', width }" />
    </div>
</template>

<style scoped>
.inventory-card {
    background: #fff;
    border-radius: 4px;
    padding: 0;
    height: v-bind(height);
    box-sizing: border-box;
}

.tab-bar {
    display: flex;
    gap: 24px;
    padding: 14px 20px 0;
    border-bottom: 1px solid #ebeef5;
    margin-bottom: 0;
}

.tab-item {
    font-size: 14px;
    font-weight: 600;
    color: #909399;
    cursor: pointer;
    padding-bottom: 10px;
    border-bottom: 2px solid transparent;
    transition: color 0.2s, border-color 0.2s;
    user-select: none;
}

.tab-item.active {
    color: #409eff;
    border-bottom-color: #409eff;
}

.tab-item:hover:not(.active) {
    color: #606266;
}
</style>
