<template>
  <AppPage>
    <n-card class="setting-card form-surface" :bordered="false">
      <n-tabs class="setting-tabs" default-value="Server" justify-content="space-evenly" type="line" @update-value="tabChange">
        <n-tab-pane name="Server" tab="服务端">
          <n-form
            class="setting-form"
            ref="serverFormRef"
            :model="serverFormModel"
            :rules="serverFormRules"
            label-placement="top"
          >
            <n-form-item label="IP段" path="ipScope" :rule="{
              required: true,
              type: 'array',
              message: 'IP段不能为空',
              trigger: ['change','blur']
            }">
              <n-select
                v-model:value="serverFormModel.ipScope"
                filterable
                multiple
                tag
                placeholder="输入，按回车确认"
                :show-arrow="false"
                :show="false"
              />
            </n-form-item>
            <n-form-item label="监听端口" path="listenPort" :rule="[
              {
                required: true,
                type: 'number',
                message: '监听端口不能为空',
                trigger: ['change','blur']
              },
              {
                min: 1120,
                type: 'number',
                message: '端口最低设置为1120',
                trigger: ['change','blur']
              },
              {
                max: 65535,
                type: 'number',
                message: '端口最高设置为65535',
                trigger: ['change','blur']
              }
            ]">
              <n-input-number :min="1120" :max="65535" v-model:value="serverFormModel.listenPort" />
            </n-form-item>
            <n-form-item label="私钥" path="privateKey">
              <n-input v-model:value="serverFormModel.privateKey" />
            </n-form-item>
            <n-form-item label="公钥" path="publicKey">
              <n-input v-model:value="serverFormModel.publicKey" />
            </n-form-item>
            <n-form-item label="上行脚本" path="postUpScript">
              <n-input v-model:value="serverFormModel.postUpScript" />
            </n-form-item>
            <n-form-item label="下行脚本" path="postDownScript">
              <n-input v-model:value="serverFormModel.postDownScript" />
            </n-form-item>
            <n-form-item class="setting-form__action">
              <n-button type="primary" @click="updateServerConf">保存服务端配置</n-button>
            </n-form-item>
          </n-form>
        </n-tab-pane>
        <n-tab-pane name="Global" tab="全局">
          <n-form
            class="setting-form"
            ref="globalFormRef"
            :model="globalFormModel"
            :rules="globalFormRules"
            label-placement="top"
          >
            <n-form-item label="公网IP" path="endpointAddress" class="setting-form__endpoint">
              <n-input v-model:value="globalFormModel.endpointAddress" />
              <n-button class="setting-form__inline-btn" size="small" secondary type="primary" @click="getPublicAddr">获取地址</n-button>
            </n-form-item>
            <n-form-item label="DNS" path="dnsServer" :rule="{
              required: true,
              type: 'array',
              message: 'dns不能为空',
              trigger: ['change','blur']
            }">
              <n-select
                v-model:value="globalFormModel.dnsServer"
                filterable
                multiple
                tag
                placeholder="输入，按回车确认"
                :show-arrow="false"
                :show="false"
              />
            </n-form-item>
            <n-form-item label="MTU" path="MTU" :rule="[
              {
                required: true,
                type: 'number',
                message: 'MTU不能为空',
                trigger: ['change','blur']
              },
              {
                min: 1120,
                type: 'number',
                message: 'MTU最低设置为100',
                trigger: ['change','blur']
              },
              {
                max: 3000,
                type: 'number',
                message: 'MTU最高设置为3000',
                trigger: ['change','blur']
              }
            ]">
              <n-input-number :min="100" :max="3000" v-model:value="globalFormModel.MTU" />
            </n-form-item>
            <n-form-item label="persistentKeepalive" path="persistentKeepalive" :rule="[
              {
                required: true,
                type: 'number',
                message: 'persistentKeepalive不能为空',
                trigger: ['change','blur']
              },
              {
                min: 15,
                type: 'number',
                message: 'persistentKeepalive最低设置为15',
                trigger: ['change','blur']
              },
              {
                max: 300,
                type: 'number',
                message: 'persistentKeepalive最高设置为300',
                trigger: ['change','blur']
              }
            ]">
              <n-input-number :min="15" :max="300" v-model:value="globalFormModel.persistentKeepalive" />
            </n-form-item>
            <n-form-item label="firewallMark" path="firewallMark">
              <n-input v-model:value="globalFormModel.firewallMark" />
            </n-form-item>
            <n-form-item label="table" path="table">
              <n-input v-model:value="globalFormModel.table" />
            </n-form-item>
            <n-form-item label="configPath" path="configFilePath">
              <n-input v-model:value="globalFormModel.configFilePath" />
            </n-form-item>
            <n-form-item class="setting-form__action">
              <n-button type="primary" @click="updateGlobalConf">保存全局配置</n-button>
            </n-form-item>
          </n-form>
        </n-tab-pane>
        <n-tab-pane name="Other" tab="其他">
            <n-button class="setting-other__add" size="small" type="primary" @click="showAddModal = !showAddModal">添加</n-button>
            <n-data-table
              :columns="tableColumns"
              :data="taleData.data"
            />
        </n-tab-pane>
      </n-tabs>
    </n-card>
    <n-modal
      :title="editFormModel.describe"
      v-model:show="showEditModal"
      preset="card"
      class="setting-modal"
      style="width: min(560px, calc(100vw - 48px))"
    >
      <n-form
        class="setting-form setting-form--modal"
        ref="editFormRef"
        :model="editFormModel"
        label-placement="top"
      >
        <n-form-item v-for="(item,index) in editFormModel.data" :label="index">
          <n-input v-if="typeof item === 'string'" v-model:value="editFormModel.data[index]" />
          <n-input-number v-else-if="typeof item === 'number'" v-model:value="editFormModel.data[index]" />
          <n-radio-group v-else-if="typeof item === 'boolean'" :value="editFormModel.data[index]">
            <n-radio :value="true" :checked="editFormModel.data[index] === true" @change="editFormModel.data[index] = true">是</n-radio>
            <n-radio :value="false" :checked="editFormModel.data[index] === false" @change="editFormModel.data[index] = false">否</n-radio>
          </n-radio-group>
        </n-form-item>
        <n-form-item label="配置描述">
          <n-input v-model:value="editFormModel.describe" />
        </n-form-item>
        <n-form-item class="setting-form__action">
          <n-button type="primary" @click="updateSetting">保存</n-button>
        </n-form-item>
      </n-form>
    </n-modal>
    <n-modal
      title="添加"
      v-model:show="showAddModal"
      preset="card"
      class="setting-modal"
      style="width: min(560px, calc(100vw - 48px))"
    >
      <n-form class="setting-form setting-form--modal" :model="addFormModel" ref="addFormRef" label-placement="top">
        <n-form-item label="Code">
          <n-input v-model:value="addFormModel.code" />
        </n-form-item>
        <n-form-item label="选项">
          <n-dynamic-input v-model:value="addFormModel.data" preset="pair" key-placeholder="键" value-placeholder="值" />
        </n-form-item>
        <n-form-item label="描述">
          <n-input v-model:value="addFormModel.describe" />
        </n-form-item>
        <n-form-item class="setting-form__action">
          <n-button type="primary" @click="addSetting">添加配置</n-button>
        </n-form-item>
      </n-form>
    </n-modal>
  </AppPage>
</template>
<script setup>

// 服务端配置表单ref
import AppPage from '@/components/page/AppPage.vue'
import api from '@/views/setting/api'
import { NButton } from 'naive-ui'
import { renderIcon } from '@/utils'
import event from '@/utils/event/event'

const { $bus } = event();
const tabCode = ref("")

// 表头
const tableColumns = [
  {
    title: 'code',
    key: 'code',
    align: 'center',
    titleAlign: 'center',
  },
  {
    title: "描述",
    key: "describe",
    align: 'center',
    titleAlign: 'center',
  },
  {
    title: '操作',
    key: 'action',
    align: 'center',
    titleAlign: 'center',
    render: (row) => {
      return [
        h(NButton, {
          size: 'small',
          color: '#4389DA',
          onClick: () => listBtn(row, "EDIT")
        }, {
          icon: renderIcon('mingcute:edit-line', { size: 14 }),
        }),
        h(NButton, {
          size: 'small',
          style: 'margin-left: 5px',
          color: '#ED1518',
          onClick: () => listBtn(row, "DELETE")
        }, {
          icon: renderIcon('icon-park-outline:delete', { size: 14 }),
        })
      ]
    }
  }
]

const taleData = ref({
  data: []
})

// 服务端表单ref
const serverFormRef = ref(null)
// 全局设置表单ref
const globalFormRef = ref(null)
// 编辑模态框表单ref
const editFormRef = ref(null)
// 添加模态框表单ref
const addFormRef = ref(null)
// 编辑模态框展示
const showEditModal = ref(false)
// 添加模态框展示
const showAddModal = ref(false)

// 服务端表单数据
const serverFormModel = ref({
  ipScope: [],
  listenPort: 51820,
  privateKey: '',
  publicKey: '',
  postUpScript: '',
  postDownScript: ''
})
// 全局设置表单数据
const globalFormModel = ref({
  MTU: 1450,
  configFilePath: '',
  dnsServer: [],
  endpointAddress: '',
  firewallMark: '',
  persistentKeepalive: 15,
  table: ''
})
// 编辑表单数据
const editFormModel = ref({
  code: '',
  data: '',
  describe: ''
})
// 添加表单数据
const addFormModel = ref({
  code: '',
  data: [
    {
      key: '',
      value: ''
    }
  ],
  describe: ''
})

// 服务端表单数据验证
const serverFormRules = {
  privateKey: [
    { required: true, message: '密钥不能为空', trigger: 'blur' }
  ],
  publicKey: [
    { required: true, message: '公钥不能为空', trigger: 'blur' }
  ]
}
// 全局表单数据验证
const globalFormRules = {
  endpointAddress: [
    { required: true, message: '公网IP不能为空', trigger: 'blur' }
  ],
  configFilePath: [
    { required: true, message: '文件地址不能为空', trigger: 'blur' }
  ]
}

// 获取服务端配置
async function getServerConfig () {
  const res = await api.getSetting({
    code: "WG_SERVER"
  })
  if (res.data.code === 200) {
    serverFormModel.value = JSON.parse(res.data.data)
  }
}

// 获取全局配置
async function getGlobalConfig () {
  const res = await api.getSetting({
    code: "WG_SETTING"
  })
  if (res.data.code === 200) {
    globalFormModel.value = JSON.parse(res.data.data)
  }
}

// 更改服务端配置
async function updateServerConf() {
  serverFormRef.value?.validate(async (errors) => {
    if (errors) {
      return errors
    }
    const res = await api.setSetting({
      code: "WG_SERVER",
      data: JSON.stringify(serverFormModel.value)
    })
    if (res.data.code === 200) {
      await getServerConfig()
      $message.success("操作成功")
    }
  })

}

// 更改全局配置
async function updateGlobalConf() {
  globalFormRef.value?.validate(async (errors) => {
    if (errors) {
      return errors
    }
    const res = await api.setSetting({
      code: "WG_SETTING",
      data: JSON.stringify(globalFormModel.value)
    })
    if (res.data.code === 200) {
      await getGlobalConfig()
      $message.success("操作成功")
    }
  })
}

// 获取公网IP地址
async function getPublicAddr() {
  const res = await api.publicAddr()
  if (res.data.code === 200) {
    globalFormModel.value.endpointAddress = res.data.data
  }
}

// 获取全部配置
async function allSetting() {
  const res = await api.allSettings()
  if (res.data.code === 200) {
    taleData.value.data = res.data.data
  }
}

// tab切换事件
function tabChange(code) {
  switch (code) {
    case "Server":
      getServerConfig()
      tabCode.value = "Server"
      break;
    case "Global":
      getGlobalConfig()
      tabCode.value = "Global"
      break;
    case "Other":
      allSetting()
      tabCode.value = "Other"
      break;
  }
}

// 列表操作按钮
function listBtn(row,code) {
  switch (code) {
    case "EDIT":
      showEditModal.value = true
      editFormModel.value.describe = row.describe
      editFormModel.value.data = JSON.parse(row.data)
      editFormModel.value.code = row.code
      break;
    case "DELETE":
      $dialog.confirm({
        type: 'warning',
        title: '删除',
        content: `是否删除设置：【${row.describe}】？`,
        async confirm() {
          const res = await api.delSetting(row.code)
          if (res.data.code === 200) {
            $message.success("操作成功")
            allSetting()
          }
        },
      })
      break;
  }
}

// 更改配置信息
async function updateSetting() {
    const res = await api.setSetting({
      code: editFormModel.value.code,
      data: JSON.stringify(editFormModel.value.data),
      describe: editFormModel.value.describe
    })
    if (res.data.code === 200) {
      showEditModal.value = false
      allSetting()
    }
}

// 添加设置
async function addSetting() {
  const dataObj = {}
  for (const item of addFormModel.value.data) {
    dataObj[item.key] = item.value
  }

  const addFormData = {
    code: addFormModel.value.code,
    data: JSON.stringify(dataObj),
    describe: addFormModel.value.describe
  }

  const res = await api.setSetting(addFormData)
  if (res.data.code === 200) {
    showAddModal.value = false
    addFormModel.value = {
      code: '',
      data: [
        {
          key: '',
          value: ''
        }
      ],
      describe: ''
    }
    allSetting()
  }
}

const handleRefreshSetting = (value) => {
  if (value) {
    if (tabCode.value === "" || tabCode.value === undefined) {
      getServerConfig()
    } else {
      switch (tabCode.value) {
        case "Server":
          getServerConfig()
          break;
        case "Global":
          getGlobalConfig()
          break;
      }
    }
  }
}

$bus.on("refreshSetting", handleRefreshSetting)

onBeforeUnmount(() => {
  $bus.off("refreshSetting", handleRefreshSetting)
})
getServerConfig()
</script>
<style scoped lang="scss">
.setting-card {
  border-radius: 14px;
  box-shadow: 0 18px 45px rgba(15, 23, 42, 0.06);
}

.setting-tabs {
  :deep(.n-tabs-nav) {
    margin-bottom: 18px;
  }
}

.setting-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 18px;
}

.setting-form--modal {
  grid-template-columns: 1fr;
}

.setting-form__wide {
  grid-column: 1 / -1;
}

.setting-form :deep(.n-form-item) {
  margin-bottom: 10px;
}

.setting-form :deep(.n-input),
.setting-form :deep(.n-input-number),
.setting-form :deep(.n-base-selection) {
  width: 100%;
}

.setting-form :deep(.n-form-item-label) {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #64748b;
}

.setting-form :deep(.n-input .n-input__input-el),
.setting-form :deep(.n-base-selection .n-base-selection-label),
.setting-form :deep(.n-input-number .n-input__input-el) {
  min-height: 42px;
}

.setting-form__action {
  grid-column: 1 / -1;
  margin-top: 8px;
}

.setting-form__action :deep(.n-button) {
  min-width: 148px;
  height: 42px;
  border-radius: 12px;
}

.setting-form__inline-btn {
  min-width: 104px;
  height: 42px;
  padding: 0 16px;
  border-radius: 12px;
}

.setting-other__add {
  float: right;
  margin-bottom: 12px;
}

.setting-form__endpoint :deep(.n-form-item-blank) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}

.setting-form__endpoint :deep(.n-input) {
  flex: 1;
}

.setting-form :deep(.n-input-number .n-input-number-button) {
  width: 34px;
}

.setting-form :deep(.n-input-number .n-input-number-button-icon) {
  font-size: 14px;
}

:deep(.setting-modal) {
  width: auto;
}

:deep(.setting-modal .n-card) {
  width: min(560px, calc(100vw - 48px));
  border-radius: 20px;
  overflow: hidden;
}

:deep(.setting-modal .n-card-header) {
  padding: 22px 24px 12px;
}

:deep(.setting-modal .n-card__content) {
  padding: 12px 24px 24px;
}

@media (max-width: 960px) {
  .setting-form {
    grid-template-columns: 1fr;
  }
}
</style>
