<template>
    <div class="app-container">
        <el-row>
            <el-col :span="22">
                <el-form ref="queryFormRef" :model="queryParams" :inline="true">
                    <el-form-item prop="base">
                        <el-select
                            v-model="queryParams.base"
                            placeholder="基准货币"
                            clearable
                            style="width: 160px"
                        >
                            <el-option
                                v-for="item in coinOptions"
                                :key="item.coinSymbol"
                                :label="item.coinSymbol"
                                :value="item.coinSymbol"
                            />
                        </el-select>
                    </el-form-item>
                    <el-form-item prop="quote">
                        <el-select
                            v-model="queryParams.quote"
                            placeholder="计价货币"
                            clearable
                            style="width: 160px"
                        >
                            <el-option
                                v-for="item in coinOptions"
                                :key="item.coinSymbol"
                                :label="item.coinSymbol"
                                :value="item.coinSymbol"
                            />
                        </el-select>
                    </el-form-item>
                    <el-form-item prop="zone">
                        <el-select
                            v-model="queryParams.zone"
                            placeholder="交易区"
                            clearable
                            style="width: 160px"
                        >
                            <el-option
                                v-for="item in zoneOptions"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value"
                            />
                        </el-select>
                    </el-form-item>
                    <el-form-item prop="isOpen">
                        <el-select
                            v-model="queryParams.isOpen"
                            placeholder="开放交易"
                            clearable
                            style="width: 160px"
                        >
                            <el-option label="开启" value="1" />
                            <el-option label="关闭" value="2" />
                        </el-select>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
                        <el-button :icon="Refresh" @click="resetQuery">重置</el-button>
                    </el-form-item>
                </el-form>
            </el-col>
            <el-col :span="2">
                <el-button type="success" @click="openDialog('add')">新增币对</el-button>
            </el-col>
        </el-row>
        <el-table :data="listdata" v-loading="loading" highlight-current-row border>
            <el-table-column align="center" prop="symbol" label="币对" />
            <el-table-column align="center" prop="base" label="交易区" />
            <el-table-column align="center" prop="isOpen" label="开放交易">
                <template #default="scope">{{ scope.row.isOpen == 1 ? '是' : '否' }}</template>
            </el-table-column>
            <el-table-column align="center" prop="publish" label="是否发布">
                <template #default="scope">{{ scope.row.publish == 1 ? '是' : '否' }}</template>
            </el-table-column>
            <el-table-column fixed="right" align="center" label="操作" min-width="260">
                <template #default="scope">
                    <el-button type="primary" size="small" @click="openDialog('update', scope.row)">编辑</el-button>
                    <el-button
                        :type="scope.row.isOpen == 1 ? 'warning' : 'success'"
                        size="small"
                        @click="toggleStatus(scope.row)"
                    >{{ scope.row.isOpen == 1 ? '关闭' : '启用' }}</el-button>
                    <el-button type="danger" size="small" @click="cancelAllOrders(scope.row)">撤销全部订单</el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-dialog v-model="dialogVisible" :title="dialogTitle" width="900px" top="5vh">
            <el-form ref="formRef" :model="form" :inline="true">
                <el-divider content-position="left">基础信息</el-divider>
                <el-form-item prop="base" label="交易币种" label-width="120px" required>
                    <el-select v-model="form.base" placeholder="请选择" style="width: 200px" filterable>
                        <el-option v-for="item in coinOptions" :key="item.coinSymbol" :label="item.coinSymbol" :value="item.coinSymbol" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="quote" label="计价币种" label-width="120px" required>
                    <el-select v-model="form.quote" placeholder="请选择" style="width: 200px" filterable>
                        <el-option v-for="item in quoteCoinOptions" :key="item.coinSymbol" :label="item.coinSymbol" :value="item.coinSymbol" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="symbol" label="交易对名称" label-width="120px" required>
                    <el-input v-model="form.symbol" disabled style="width: 200px" />
                </el-form-item>
                <el-form-item prop="volumePre" label="币种精度" label-width="120px" required>
                    <el-input-number v-model="form.volumePre" :min="0" :max="18" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="pricePre" label="价格精度" label-width="120px" required>
                    <el-input-number v-model="form.pricePre" :min="0" :max="18" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="category" label="交易对分类" label-width="120px" required>
                    <el-select v-model="form.category" placeholder="请选择" style="width: 200px" clearable>
                        <el-option label="主流币" value="1" />
                        <el-option label="创新区" value="2" />
                        <el-option label="新币" value="3" />
                        <el-option label="观察区" value="4" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="label" label="标签" label-width="120px">
                    <el-select v-model="form.label" placeholder="请选择" style="width: 200px" clearable>
                        <el-option label="减半" :value="1" />
                        <el-option label="上新" :value="2" />
                        <el-option label="热门" :value="3" />
                        <el-option label="ETF" :value="4" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="isOpen" label="状态" label-width="120px">
                    <el-select v-model="form.isOpen" style="width: 200px">
                        <el-option label="开启" :value="1" />
                        <el-option label="关闭" :value="2" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="customize" label="是否特殊币对" label-width="120px">
                    <el-select v-model="form.customize" style="width: 200px">
                        <el-option label="自定义" :value="1" />
                        <el-option label="非自定义" :value="2" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="sort" label="排序" label-width="120px">
                    <el-input-number v-model="form.sort" :min="0" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="publish" label="是否发布" label-width="120px" required>
                    <el-select v-model="form.publish" style="width: 200px">
                        <el-option label="是" :value="1" />
                        <el-option label="否" :value="2" />
                    </el-select>
                </el-form-item>

                <el-divider content-position="left">交易设置</el-divider>
                <el-form-item prop="takerFee" label="Taker手续费率" label-width="120px" required>
                    <el-input v-model="form.takerFee" placeholder="如：0.001" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="makerFee" label="Maker手续费率" label-width="120px" required>
                    <el-input v-model="form.makerFee" placeholder="如：0.001" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="maxOrdersPerUser" label="委托单数量上限" label-width="120px">
                    <el-input-number v-model="form.maxOrdersPerUser" :min="0" :precision="0" :controls="false" placeholder="整数" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="dailyVolumeLimit" label="单日交易额上限" label-width="120px">
                    <el-input-number v-model="form.dailyVolumeLimit" :min="0" :controls="false" placeholder="整数" style="width: 200px" /><span style="margin-left: 4px">USDT</span>
                </el-form-item>
                <el-form-item prop="limitPriceMin" label="限价单最小价格" label-width="120px">
                    <el-input v-model="form.limitPriceMin" placeholder="限价单最小价格" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="limitVolumeMin" label="限价单最小数量" label-width="120px">
                    <el-input v-model="form.limitVolumeMin" placeholder="限价单最小数量" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="marketBuyMin" label="市价买最小值" label-width="120px">
                    <el-input v-model="form.marketBuyMin" placeholder="市价买最小值" style="width: 200px" />
                </el-form-item>
                <el-form-item prop="marketSellMin" label="市价卖最小值" label-width="120px">
                    <el-input v-model="form.marketSellMin" placeholder="市价卖最小值" style="width: 200px" />
                </el-form-item>
                <el-divider content-position="left">滑点设置</el-divider>
                <div v-for="(item, index) in form.slippageList" :key="index" style="margin-bottom: 8px">
                    <el-form-item label="交易额" label-width="120px">
                        <el-input v-model="item.amountMin" placeholder="0" style="width: 130px" />&nbsp;~&nbsp;
                        <el-input v-model="item.amountMax" placeholder="无上限" style="width: 130px" />
                        <span style="margin: 0 8px">| USDT</span>
                    </el-form-item>
                    <el-form-item label="滑点" label-width="60px">
                        <el-input v-model="item.slippage" placeholder="如：0.1" style="width: 100px" /><span>%</span>
                        <el-button type="danger" link @click="removeSlippage(index)" style="margin-left: 12px">删除</el-button>
                    </el-form-item>
                </div>
                <el-button type="primary" link @click="addSlippage" style="margin-left: 120px; margin-bottom: 16px">+ 添加滑点设置</el-button>

                <el-divider content-position="left">档位精度</el-divider>
                <el-form-item prop="depth0Pre" label="深度档位精度0" label-width="120px">
                    <el-select v-model="form.depth0Pre" style="width: 200px">
                        <el-option v-for="i in 9" :key="i - 1" :label="String(i - 1)" :value="i - 1" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="depth1Pre" label="深度档位精度1" label-width="120px">
                    <el-select v-model="form.depth1Pre" style="width: 200px">
                        <el-option v-for="i in 9" :key="i - 1" :label="String(i - 1)" :value="i - 1" />
                    </el-select>
                </el-form-item>
                <el-form-item prop="depth2Pre" label="深度档位精度2" label-width="120px">
                    <el-select v-model="form.depth2Pre" style="width: 200px">
                        <el-option v-for="i in 9" :key="i - 1" :label="String(i - 1)" :value="i - 1" />
                    </el-select>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button type="primary" :loading="submitting" @click="submitForm">保存</el-button>
                <el-button @click="closeDialog">取消</el-button>
            </template>
        </el-dialog>
        <pagination
            v-if="total > 0"
            :total="total"
            v-model:page="queryParams.pageNo"
            v-model:limit="queryParams.pageSize"
            @pagination="handleQuery"
        />
    </div>
</template>
<script lang="ts">
name: "symbolConfig";
</script>
<script lang="ts" setup>
import { nextTick, reactive, onMounted, ref, watch, computed } from "vue";
import { Search, Refresh } from "@element-plus/icons-vue";
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
import {
    configSymbolPage,
    configSymbolDetail,
    configSymbolCreate,
    configSymbolUpdate,
    configSymbolDelete,
    configSymbolToggleStatus,
    configSymbolCancelAllOrders,
    configCoinSymbolList,
} from "@/api/coinSpot";
import { ConfigSymbol, ConfigSymbolSlippage, CoinSymbolConfig } from "@/types/api/coinspot";

const queryFormRef = ref(ElForm);
const formRef = ref();

const loading = ref(true);
const total = ref(0);
const listdata = ref<ConfigSymbol[]>([]);
const dialogVisible = ref(false);
const dialogTitle = ref("新增");
const submitting = ref(false);
const coinOptions = ref<CoinSymbolConfig[]>([]);

const zoneOptions = [
    { label: "主区", value: "1" },
    { label: "创新区", value: "2" },
];

const queryParams = reactive({
    base: "",
    quote: "",
    zone: "",
    isOpen: "",
    pageNo: 1,
    pageSize: 15,
});

const emptySlippage = (): ConfigSymbolSlippage => ({
    amountMin: "",
    amountMax: "",
    slippage: "",
    isOpen: 1,
});

const form = reactive<ConfigSymbol>({
    symbol: "",
    base: "",
    quote: "",
    isOpen: 1,
    takerFee: "",
    makerFee: "",
    depth0Pre: 0,
    depth1Pre: 0,
    depth2Pre: 0,
    pricePre: 0,
    volumePre: 0,
    publish: 1,
    customize: 2,
    category: "",
    label: undefined,
    sort: 0,
    maxOrdersPerUser: undefined,
    dailyVolumeLimit: undefined,
    limitPriceMin: "",
    limitVolumeMin: "",
    marketBuyMin: "",
    marketSellMin: "",
    slippageList: [],
});

function loadCoinOptions() {
    configCoinSymbolList().then((res: any) => {
        if (res.data) {
            coinOptions.value = res.data;
        }
    });
}

const quoteCoinOptions = computed(() =>
    coinOptions.value.filter(c => c.isQuote === 1)
);

watch([() => form.base, () => form.quote], ([base, quote]) => {
    if (base && quote) {
        form.symbol = base.toUpperCase() + quote.toUpperCase();
    }
});

function handleQuery() {
    loading.value = true;
    configSymbolPage({
        pageNo: queryParams.pageNo,
        pageSize: queryParams.pageSize,
        base: queryParams.base || undefined,
        quote: queryParams.quote || undefined,
        zone: queryParams.zone || undefined,
        isOpen: queryParams.isOpen || undefined,
    }).then((res: any) => {
        listdata.value = res.data.content;
        total.value = res.data.totalElements;
        loading.value = false;
    });
}

function resetQuery() {
    queryFormRef.value.resetFields();
    handleQuery();
}

function openDialog(type: string, row?: ConfigSymbol) {
    formRef.value?.resetFields();
    dialogVisible.value = true;
    dialogTitle.value = type === "add" ? "新增" : "修改";
    if (row) {
        configSymbolDetail(row.id!).then((res: any) => {
            if (res.data) {
                const d = res.data;
                Object.assign(form, {
                    id: d.id,
                    symbol: d.symbol,
                    base: d.base,
                    quote: d.quote,
                    isOpen: d.isOpen,
                    takerFee: d.takerFee != null ? String(d.takerFee) : "",
                    makerFee: d.makerFee != null ? String(d.makerFee) : "",
                    depth0Pre: d.depth0Pre,
                    depth1Pre: d.depth1Pre,
                    depth2Pre: d.depth2Pre,
                    pricePre: d.pricePre,
                    volumePre: d.volumePre,
                    publish: d.publish,
                    customize: d.customize,
                    sort: d.sort,
                    category: d.category || "",
                    label: d.label,
                    limitPriceMin: d.limitPriceMin != null ? String(d.limitPriceMin) : "",
                    limitVolumeMin: d.limitVolumeMin != null ? String(d.limitVolumeMin) : "",
                    marketBuyMin: d.marketBuyMin != null ? String(d.marketBuyMin) : "",
                    marketSellMin: d.marketSellMin != null ? String(d.marketSellMin) : "",
                    maxOrdersPerUser: d.maxOrdersPerUser,
                    dailyVolumeLimit: d.dailyVolumeLimit,
                    description: d.description,
                    slippageList: d.slippageList && d.slippageList.length > 0
                        ? d.slippageList
                        : [],
                });
                nextTick(() => formRef.value?.clearValidate());
            }
        });
    } else {
        Object.assign(form, {
            id: undefined,
            symbol: "",
            base: "",
            quote: "",
            isOpen: 1,
            takerFee: "",
            makerFee: "",
            depth0Pre: 0,
            depth1Pre: 0,
            depth2Pre: 0,
            pricePre: 0,
            volumePre: 0,
            publish: 1,
            customize: 2,
            category: "",
            label: undefined,
            sort: 0,
            maxOrdersPerUser: undefined,
            dailyVolumeLimit: undefined,
            limitPriceMin: "",
            limitVolumeMin: "",
            marketBuyMin: "",
            marketSellMin: "",
            slippageList: [],
        });
        nextTick(() => formRef.value?.clearValidate());
    }
}

function closeDialog() {
    formRef.value?.resetFields();
    dialogVisible.value = false;
}

async function submitForm() {
    // 必填校验
    if (!form.symbol || !form.symbol.trim()) { ElMessage.error("请输入交易对名称"); return; }
    if (!form.base) { ElMessage.error("请选择交易币种"); return; }
    if (!form.quote) { ElMessage.error("请选择计价币种"); return; }
    if (form.pricePre == null) { ElMessage.error("请设置价格精度"); return; }
    if (form.volumePre == null) { ElMessage.error("请设置币种精度"); return; }
    if (form.publish == null) { ElMessage.error("请选择是否发布"); return; }
    if (!form.takerFee || !form.takerFee.trim()) { ElMessage.error("请输入Taker手续费率"); return; }
    if (isNaN(Number(form.takerFee))) { ElMessage.error("Taker手续费率必须为数值"); return; }
    if (!form.makerFee || !form.makerFee.trim()) { ElMessage.error("请输入Maker手续费率"); return; }
    if (isNaN(Number(form.makerFee))) { ElMessage.error("Maker手续费率必须为数值"); return; }

    // 校验滑点配置（amountMax 可以为空表示无上限）
    const slippageList = (form.slippageList || [])
        .filter(item => !(item.amountMin === "" && item.amountMax === "" && item.slippage === ""));
    for (const item of slippageList) {
        if (item.amountMin === "" || item.amountMin == null) {
            ElMessage.error("滑点配置中交易额（左值）不能为空");
            return;
        }
        if (item.slippage === "" || item.slippage == null) {
            ElMessage.error("滑点配置中滑点不能为空");
            return;
        }
        const min = Number(item.amountMin);
        const slip = Number(item.slippage);
        if (isNaN(min) || isNaN(slip)) {
            ElMessage.error("滑点配置中交易额和滑点必须为数值");
            return;
        }
        if (item.amountMax !== "" && item.amountMax != null) {
            const max = Number(item.amountMax);
            if (isNaN(max)) {
                ElMessage.error("滑点配置中交易额必须为数值");
                return;
            }
            if (min >= max) {
                ElMessage.error("滑点配置中交易额左值必须小于右值");
                return;
            }
        }
    }
    // 无上限区间最多只能有一个
    const unlimitedCount = slippageList.filter(item => item.amountMax === "" || item.amountMax == null).length;
    if (unlimitedCount > 1) {
        ElMessage.error("滑点配置中无上限区间只能有一个");
        return;
    }
    // 检查区间是否重叠（无上限区间 max 视为 Infinity，排在最后）
    if (slippageList.length > 1) {
        const sorted = [...slippageList].map(item => ({
            min: Number(item.amountMin),
            max: (item.amountMax !== "" && item.amountMax != null) ? Number(item.amountMax) : Infinity,
        }));
        sorted.sort((a, b) => a.min - b.min);
        for (let i = 1; i < sorted.length; i++) {
            if (sorted[i].min < sorted[i - 1].max) {
                ElMessage.error(`滑点配置区间重叠：${sorted[i - 1].min}-${sorted[i - 1].max} 与 ${sorted[i].min}-${sorted[i].max}`);
                return;
            }
        }
    }
    const payload = { ...form, slippageList };

    submitting.value = true;
    try {
        const api = form.id ? configSymbolUpdate : configSymbolCreate;
        await api(payload);
        closeDialog();
        ElMessage.success("操作成功");
        handleQuery();
    } catch {
        // error message already shown by response interceptor
    } finally {
        submitting.value = false;
    }
}

function toggleStatus(row: ConfigSymbol) {
    const action = row.isOpen == 1 ? "关闭" : "启用";
    ElMessageBox.confirm(`确认${action}币对 ${row.symbol}？`, "提示", { type: "warning" }).then(() => {
        configSymbolToggleStatus(row.id!).then((res: any) => {
            ElMessage.success("操作成功");
            handleQuery();
        });
    });
}

function cancelAllOrders(row: ConfigSymbol) {
    ElMessageBox.confirm(`确认撤销 ${row.symbol} 的全部订单？`, "警告", { type: "warning" }).then(() => {
        configSymbolCancelAllOrders(row.symbol).then((res: any) => {
            ElMessage.success("已提交撤单请求");
            handleQuery();
        });
    });
}

function addSlippage() {
    form.slippageList = form.slippageList || [];
    form.slippageList.push(emptySlippage());
}

function removeSlippage(index: number) {
    form.slippageList!.splice(index, 1);
}

onMounted(() => {
    loadCoinOptions();
    handleQuery();
});
</script>
<style lang="less" scoped>
.el-divider {
    margin: 16px 0;
    :deep(.el-divider__text) {
        font-size: 16px;
        font-weight: 700;
    }
}
:deep(.el-input-number .el-input__inner) {
    text-align: left;
}
</style>
