<script setup lang="ts">
import { ref, reactive, onMounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  configRobotPage,
  configRobotCreate,
  configRobotUpdate,
  configRobotDelete,
  configRobotSymbols,
} from '@/api/coinSpot'
import type { ConfigRobot } from '@/types/api/coinspot'

const loading = ref(false)
const tableData = ref<ConfigRobot[]>([])
const total = ref(0)
const pageNo = ref(1)
const pageSize = ref(15)
const searchSymbol = ref('')
const searchStatus = ref<number | undefined>(undefined)

const dialogVisible = ref(false)
const dialogTitle = ref('新增')
const formRef = ref()
const submitting = ref(false)
const isEdit = ref(false)
const symbolOptions = ref<string[]>([])

const DEFAULT_FORM: ConfigRobot = {
  symbol: '',
  trend: 1,
  openPrice: '',
  targetPrice: undefined,
  hoverRange: '0.0200',
  minChangeRate: '0.001000',
  maxChangeRate: '0.005000',
  hoverMinChangeRate: '0.000500',
  hoverMaxChangeRate: '0.002000',
  bridgeMinRatio: '0.0500',
  bridgeMaxRatio: '0.1000',
  upProbability: undefined,
  intervalMs: 3000,
  klineMaxHighRatio: '0.0050',
  klineMaxLowRatio: '0.0050',
  minuteChangeLimit: undefined,
  status: 1,
  remark: '',
}

const form = reactive<ConfigRobot>({ ...DEFAULT_FORM })

const trendOptions = [
  { label: '涨', value: 1 },
  { label: '跌', value: 2 },
  { label: '横盘', value: 3 },
]

const statusOptions = [
  { label: '趋势运行', value: 1 },
  { label: '已停止', value: 2 },
  { label: '盘整震荡(废弃)', value: 3 },
  { label: '成桥过渡', value: 4 },
]

async function fetchData() {
  loading.value = true
  try {
    const res = await configRobotPage({
      pageNo: pageNo.value,
      pageSize: pageSize.value,
      symbol: searchSymbol.value || undefined,
      status: searchStatus.value,
    })
    const data = res as any
    tableData.value = data?.data?.content ?? []
    total.value = data?.data?.totalElements ?? 0
  } finally {
    loading.value = false
  }
}

async function fetchSymbols() {
  const res = await configRobotSymbols()
  symbolOptions.value = (res as any)?.data ?? res ?? []
}

function handleSearch() {
  pageNo.value = 1
  fetchData()
}

function handleReset() {
  searchSymbol.value = ''
  searchStatus.value = undefined
  pageNo.value = 1
  fetchData()
}

function openDialog(row?: ConfigRobot) {
  dialogVisible.value = true
  formRef.value?.resetFields()
  if (row) {
    dialogTitle.value = '编辑'
    isEdit.value = true
    nextTick(() => {
      Object.assign(form, {
        id: row.id,
        symbol: row.symbol,
        trend: row.trend,
        openPrice: row.openPrice,
        targetPrice: row.targetPrice,
        hoverRange: row.hoverRange,
        minChangeRate: row.minChangeRate,
        maxChangeRate: row.maxChangeRate,
        hoverMinChangeRate: row.hoverMinChangeRate,
        hoverMaxChangeRate: row.hoverMaxChangeRate,
        bridgeMinRatio: row.bridgeMinRatio,
        bridgeMaxRatio: row.bridgeMaxRatio,
        upProbability: row.upProbability,
        intervalMs: row.intervalMs,
        klineMaxHighRatio: row.klineMaxHighRatio,
        klineMaxLowRatio: row.klineMaxLowRatio,
        minuteChangeLimit: row.minuteChangeLimit,
        status: row.status,
        remark: row.remark ?? '',
      })
      setTimeout(() => formRef.value?.clearValidate(), 0)
    })
  } else {
    dialogTitle.value = '新增'
    isEdit.value = false
    nextTick(() => {
      Object.assign(form, { ...DEFAULT_FORM, id: undefined })
      setTimeout(() => formRef.value?.clearValidate(), 0)
    })
  }
}

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

async function handleSubmit() {
  const valid = await formRef.value?.validate().catch(() => false)
  if (!valid) return
  submitting.value = true
  try {
    const payload: ConfigRobot = {
      ...form,
      symbol: form.symbol.trim().toLowerCase(),
      targetPrice: normalizeOptionalDecimal(form.targetPrice),
      upProbability: normalizeOptionalDecimal(form.upProbability),
      minuteChangeLimit: normalizeOptionalDecimal(form.minuteChangeLimit),
      remark: form.remark?.trim() || undefined,
    }
    if (isEdit.value) {
      await configRobotUpdate(payload)
      ElMessage.success('修改成功')
    } else {
      await configRobotCreate(payload)
      ElMessage.success('新增成功')
    }
    closeDialog()
    fetchData()
  } catch (e: any) {
    // error handled by request interceptor
  } finally {
    submitting.value = false
  }
}

async function handleDelete(row: ConfigRobot) {
  await ElMessageBox.confirm(`确定删除交易对 ${row.symbol} 的机器人配置吗？`, '提示', {
    type: 'warning',
  })
  await configRobotDelete(row.id!)
  ElMessage.success('删除成功')
  fetchData()
}

function handleSizeChange(size: number) {
  pageSize.value = size
  pageNo.value = 1
  fetchData()
}

function handlePageChange(page: number) {
  pageNo.value = page
  fetchData()
}

function trendLabel(val: number) {
  const item = trendOptions.find(t => t.value === val)
  return item?.label ?? String(val)
}

function statusTag(val: number) {
  switch (val) {
    case 1: return 'success'
    case 2: return 'info'
    case 3: return 'warning'
    case 4: return ''
    default: return 'info'
  }
}

function statusLabel(val: number) {
  const item = statusOptions.find(t => t.value === val)
  return item?.label ?? String(val)
}

function parsePositiveNum(val: unknown): number | null {
  if (val === '' || val === null || val === undefined) {
    return null
  }
  const n = Number(val)
  return Number.isFinite(n) ? n : null
}

function validatePositive(_rule: unknown, value: unknown, callback: (e?: Error) => void) {
  const n = parsePositiveNum(value)
  if (n === null || n <= 0) {
    callback(new Error('必须大于 0'))
    return
  }
  callback()
}

function validateMinMaxPair(minField: keyof ConfigRobot, maxField: keyof ConfigRobot, label: string) {
  return (_rule: unknown, _value: unknown, callback: (e?: Error) => void) => {
    const min = parsePositiveNum(form[minField])
    const max = parsePositiveNum(form[maxField])
    if (min !== null && max !== null && min > max) {
      callback(new Error(`${label}最小值不能大于最大值`))
      return
    }
    callback()
  }
}

function validateOptionalProbability(_rule: unknown, value: unknown, callback: (e?: Error) => void) {
  if (value === '' || value === null || value === undefined) {
    callback()
    return
  }
  const n = Number(value)
  if (!Number.isFinite(n) || n < 0 || n > 1) {
    callback(new Error('必须在 0~1 之间'))
    return
  }
  callback()
}

function validateOptionalPositive(_rule: unknown, value: unknown, callback: (e?: Error) => void) {
  if (value === '' || value === null || value === undefined) {
    callback()
    return
  }
  const n = Number(value)
  if (!Number.isFinite(n) || n <= 0) {
    callback(new Error('必须大于 0'))
    return
  }
  callback()
}

function normalizeOptionalDecimal(val: unknown): string | undefined {
  if (val === '' || val === null || val === undefined) {
    return undefined
  }
  return String(val)
}

const rules = {
  symbol: [{ required: true, message: '请选择交易对', trigger: 'change' }],
  trend: [{ required: true, message: '请选择趋势方向', trigger: 'change' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }],
  openPrice: [
    { required: true, message: '请输入起始参考价', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
  ],
  hoverRange: [
    { required: true, message: '请输入盘整区间比例', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
  ],
  minChangeRate: [
    { required: true, message: '请输入趋势最小波动率', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
    { validator: validateMinMaxPair('minChangeRate', 'maxChangeRate', '趋势波动率'), trigger: 'blur' },
  ],
  maxChangeRate: [
    { required: true, message: '请输入趋势最大波动率', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
    { validator: validateMinMaxPair('minChangeRate', 'maxChangeRate', '趋势波动率'), trigger: 'blur' },
  ],
  hoverMinChangeRate: [
    { required: true, message: '请输入盘整最小波动率', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
    { validator: validateMinMaxPair('hoverMinChangeRate', 'hoverMaxChangeRate', '盘整波动率'), trigger: 'blur' },
  ],
  hoverMaxChangeRate: [
    { required: true, message: '请输入盘整最大波动率', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
    { validator: validateMinMaxPair('hoverMinChangeRate', 'hoverMaxChangeRate', '盘整波动率'), trigger: 'blur' },
  ],
  bridgeMinRatio: [
    { required: true, message: '请输入成桥最小比例', trigger: 'blur' },
    { validator: validateMinMaxPair('bridgeMinRatio', 'bridgeMaxRatio', '成桥比例'), trigger: 'blur' },
  ],
  bridgeMaxRatio: [
    { required: true, message: '请输入成桥最大比例', trigger: 'blur' },
    { validator: validateMinMaxPair('bridgeMinRatio', 'bridgeMaxRatio', '成桥比例'), trigger: 'blur' },
  ],
  klineMaxHighRatio: [
    { required: true, message: '请输入K线最高价上限比例', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
  ],
  klineMaxLowRatio: [
    { required: true, message: '请输入K线最低价下限比例', trigger: 'blur' },
    { validator: validatePositive, trigger: 'blur' },
  ],
  intervalMs: [
    { required: true, message: '请输入执行间隔', trigger: 'blur' },
    {
      validator: (_r: unknown, v: unknown, cb: (e?: Error) => void) => {
        const n = Number(v)
        if (!Number.isFinite(n) || n < 1) {
          cb(new Error('不能小于 1ms'))
          return
        }
        cb()
      },
      trigger: 'blur',
    },
  ],
  targetPrice: [{ validator: validateOptionalPositive, trigger: 'blur' }],
  upProbability: [{ validator: validateOptionalProbability, trigger: 'blur' }],
  minuteChangeLimit: [{ validator: validateOptionalPositive, trigger: 'blur' }],
}

onMounted(() => {
  fetchData()
  fetchSymbols()
})
</script>

<template>
  <div class="robot-config-page">
    <!-- Search -->
    <el-card class="search-card">
      <el-form :inline="true" :model="{ searchSymbol, searchStatus }">
        <el-form-item label="交易对">
          <el-select v-model="searchSymbol" clearable placeholder="全部" filterable style="width:160px">
            <el-option v-for="s in symbolOptions" :key="s" :label="s" :value="s" />
          </el-select>
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchStatus" clearable placeholder="全部" style="width:160px">
            <el-option v-for="s in statusOptions" :key="s.value" :label="s.label" :value="s.value" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">查询</el-button>
          <el-button @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- Toolbar -->
    <el-card class="toolbar-card">
      <el-button type="primary" @click="openDialog()">新增配置</el-button>
    </el-card>

    <!-- Table -->
    <el-card>
      <el-table :data="tableData" v-loading="loading" stripe>
        <el-table-column prop="symbol" label="交易对" min-width="100" />
        <el-table-column prop="trend" label="趋势" width="70">
          <template #default="{ row }">{{ trendLabel(row.trend) }}</template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="100">
          <template #default="{ row }">
            <el-tag :type="statusTag(row.status)">{{ statusLabel(row.status) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="openPrice" label="起始参考价" width="120" />
        <el-table-column prop="targetPrice" label="目标价格" width="110" />
        <el-table-column prop="hoverRange" label="盘整区间比" width="105" />
        <el-table-column prop="minChangeRate" label="趋势最小波动" width="115" />
        <el-table-column prop="hoverMinChangeRate" label="盘整最小波动" width="115" />
        <el-table-column prop="bridgeMinRatio" label="成桥最小比" width="105" />
        <el-table-column prop="bridgeMaxRatio" label="成桥最大比" width="105" />
        <el-table-column prop="upProbability" label="上涨概率" width="90" />
        <el-table-column prop="intervalMs" label="间隔(ms)" width="95" />
        <el-table-column prop="remark" label="备注" min-width="120" show-overflow-tooltip />
        <el-table-column prop="createTime" label="创建时间" width="160" />
        <el-table-column prop="updateTime" label="更新时间" width="160" />
        <el-table-column label="操作" width="140" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" size="small" @click="openDialog(row)">编辑</el-button>
            <el-button link type="danger" size="small" @click="handleDelete(row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <el-pagination
        v-if="total > 0"
        style="margin-top:16px;justify-content:flex-end"
        background
        layout="total, sizes, prev, pager, next"
        :total="total"
        :page-size="pageSize"
        :current-page="pageNo"
        :page-sizes="[15, 30, 50]"
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
      />
    </el-card>

    <!-- Dialog -->
    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="680px"
      :close-on-click-modal="false"
      @closed="closeDialog"
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="150px">
        <!-- 基本信息 -->
        <el-form-item label="交易对" prop="symbol" v-if="!isEdit">
          <el-select v-model="form.symbol" placeholder="请选择自定义币对" filterable style="width:100%">
            <el-option v-for="s in symbolOptions" :key="s" :label="s" :value="s" />
          </el-select>
        </el-form-item>
        <el-form-item label="交易对" v-else>
          <el-input :model-value="form.symbol" disabled />
        </el-form-item>

        <el-form-item label="趋势方向" prop="trend">
          <el-radio-group v-model="form.trend">
            <el-radio v-for="t in trendOptions" :key="t.value" :value="t.value">{{ t.label }}</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="form.status">
            <el-radio v-for="s in statusOptions" :key="s.value" :value="s.value">{{ s.label }}</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-divider content-position="left">价格参数</el-divider>

        <el-form-item label="起始参考价" prop="openPrice">
          <el-input v-model="form.openPrice" placeholder="0.00" />
        </el-form-item>

        <el-form-item label="目标价格" prop="targetPrice">
          <el-input v-model="form.targetPrice" placeholder="选填，留空则无目标一直运行" />
          <div class="field-tip">留空(NULL)表示无目标，一直趋势运行</div>
        </el-form-item>

        <el-form-item label="盘整区间比例" prop="hoverRange">
          <el-input v-model="form.hoverRange" placeholder="0.0200" />
          <div class="field-tip">目标价 ±2%，横盘模式不生效</div>
        </el-form-item>

        <el-divider content-position="left">波动率参数（趋势阶段）</el-divider>

        <el-form-item label="趋势最小波动率" prop="minChangeRate">
          <el-input v-model="form.minChangeRate" placeholder="0.001000" />
        </el-form-item>

        <el-form-item label="趋势最大波动率" prop="maxChangeRate">
          <el-input v-model="form.maxChangeRate" placeholder="0.005000" />
        </el-form-item>

        <el-divider content-position="left">波动率参数（盘整阶段）</el-divider>

        <el-form-item label="盘整最小波动率" prop="hoverMinChangeRate">
          <el-input v-model="form.hoverMinChangeRate" placeholder="0.000500" />
          <div class="field-tip">横盘模式不生效</div>
        </el-form-item>

        <el-form-item label="盘整最大波动率" prop="hoverMaxChangeRate">
          <el-input v-model="form.hoverMaxChangeRate" placeholder="0.002000" />
          <div class="field-tip">横盘模式不生效</div>
        </el-form-item>

        <el-divider content-position="left">成桥参数</el-divider>

        <el-form-item label="成桥最小比例" prop="bridgeMinRatio">
          <el-input v-model="form.bridgeMinRatio" placeholder="0.0500" />
          <div class="field-tip">每次进入桥区间时在[min,max]区间随机，两者均为0时默认5%</div>
        </el-form-item>

        <el-form-item label="成桥最大比例" prop="bridgeMaxRatio">
          <el-input v-model="form.bridgeMaxRatio" placeholder="0.1000" />
          <div class="field-tip">必定成桥，两者均为0时默认10%</div>
        </el-form-item>

        <el-divider content-position="left">K线约束参数</el-divider>

        <el-form-item label="K线最高价上限比" prop="klineMaxHighRatio">
          <el-input v-model="form.klineMaxHighRatio" placeholder="0.0050" />
          <div class="field-tip">high ≤ close × (1 + ratio)</div>
        </el-form-item>

        <el-form-item label="K线最低价下限比" prop="klineMaxLowRatio">
          <el-input v-model="form.klineMaxLowRatio" placeholder="0.0050" />
          <div class="field-tip">low ≥ close × (1 − ratio)</div>
        </el-form-item>

        <el-form-item label="分钟涨跌幅限制" prop="minuteChangeLimit">
          <el-input v-model="form.minuteChangeLimit" placeholder="选填，如 0.10 = 10%，NULL不限制" />
          <div class="field-tip">超出边界时从边界反向弹回随机步长，不填不限制</div>
        </el-form-item>

        <el-divider content-position="left">其他参数</el-divider>

        <el-form-item label="上涨概率" prop="upProbability">
          <el-input v-model="form.upProbability" placeholder="选填，如 0.6000" />
          <div class="field-tip">NULL时由趋势自动推导：涨=0.65 跌=0.35 横盘=0.50</div>
        </el-form-item>

        <el-form-item label="执行间隔(ms)" prop="intervalMs">
          <el-input-number v-model="form.intervalMs" :min="1" style="width:100%" />
        </el-form-item>

        <el-form-item label="备注">
          <el-input v-model="form.remark" type="textarea" :rows="2" maxlength="200" show-word-limit />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.robot-config-page {
  padding: 16px;
}
.search-card {
  margin-bottom: 12px;
}
.toolbar-card {
  margin-bottom: 12px;
}
:deep(.el-divider__text) {
  font-size: 14px;
  font-weight: 700;
}
:deep(.el-input-number .el-input__inner) {
  text-align: left;
}
.field-tip {
  color: #999;
  font-size: 12px;
  line-height: 1.4;
}
</style>
