<script setup lang="ts">
import { ProModal } from 'antdv-pro-modal';
import { Modal, message } from 'ant-design-vue/es';
import { nextTick, onMounted, reactive, ref, toRaw } from 'vue';
import {
  addNeInfo,
  delNeInfo,
  listAllNeInfo,
  getNeInfo,
  updateNeInfo,
} from '@/api/ne/neInfo';
import { neHostAuthorizedRSA, testNeHost } from '@/api/ne/neHost';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import { fnToStepName } from '../hooks/useStep';
import useI18n from '@/hooks/useI18n';
import useDictStore from '@/store/modules/dict';

const { getDict } = useDictStore();
const { t } = useI18n();

/**字典数据 */
let dict: {
  /**主机类型 */
  neHostType: DictType[];
  /**分组 */
  neHostGroupId: DictType[];
  /**认证模式 */
  neHostAuthMode: DictType[];
} = reactive({
  neHostType: [],
  neHostGroupId: [],
  neHostAuthMode: [],
});

/**标签对象信息状态类型 */
type TabStateType = {
  /**激活选中 */
  activeKey: string;
  /**页签数据 */
  panes: Record<string, any>[];
  /**等待loading */
  confirmLoading: boolean;
};

/**标签对象信息状态 */
const tabState: TabStateType = reactive({
  activeKey: 'neType@neId',
  panes: [],
  confirmLoading: false,
});

/**对话框对象信息状态类型 */
type ModalStateType = {
  /**新增框或修改框是否显示 */
  openByEdit: boolean;
  /**标题 */
  title: string;
  /**表单数据 */
  from: Record<string, any>;
  /**确定按钮 loading */
  confirmLoading: boolean;
  /**更新加载数据按钮 loading */
  loadDataLoading: boolean;
};

/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
  openByEdit: false,
  title: '网元配置',
  from: {
    id: undefined,
    neType: '',
    neId: '',
    neName: '',
    ip: '',
    port: 33030,
    pvFlag: 'PNF',
    rmUid: '',
    neAddress: '',
    dn: '-',
    vendorName: '-',
    province: 'Area',
    hosts: [],
  },
  confirmLoading: false,
  loadDataLoading: false,
});

/**表格状态 */
let tableState: any = reactive({
  loading: false,
  size: 'small',
  seached: true,
  data: [],
  selectedRowKeys: [],
});

/**表格字段列 */
let tableColumns: any = [
  {
    title: t('views.ne.common.neType'),
    dataIndex: 'neType',
    align: 'left',
    width: 100,
  },
  {
    title: t('views.ne.common.neId'),
    dataIndex: 'neId',
    align: 'left',
    width: 150,
  },
  {
    title: t('views.ne.common.ipAddr'),
    dataIndex: 'ip',
    align: 'left',
    width: 150,
  },
  {
    title: t('views.ne.neHost.user'),
    dataIndex: 'hosts',
    customRender(opt: any) {
      const hosts = opt.value;
      return hosts[0].user;
    },
    align: 'left',
    width: 100,
  },
  {
    title: t('common.operate'),
    dataIndex: 'operation',
    key: 'operation',
    align: 'left',
    width: 90,
  },
];

/**
 * 测试主机连接
 */
function fnHostTest(row: Record<string, any>) {
  if (tabState.confirmLoading || !row.addr || !row.port) return;
  tabState.confirmLoading = true;
  const hide = message.loading(t('common.loading'), 0);
  testNeHost(row)
    .then(res => {
      if (res.code === RESULT_CODE_SUCCESS) {
        message.success({
          content: `${row.addr}:${row.port} ${t('views.ne.neHost.testOk')}`,
          duration: 2,
        });
      } else {
        message.error({
          content: `${row.addr}:${row.port} ${res.msg}`,
          duration: 2,
        });
      }
    })
    .finally(() => {
      hide();
      tabState.confirmLoading = false;
    });
}

/**测试主机连接-免密直连 */
function fnHostAuthorized(row: Record<string, any>) {
  if (tabState.confirmLoading || !row.addr) return;

  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.ne.neHost.authRSATip'),
    onOk: () => {
      tabState.confirmLoading = true;
      neHostAuthorizedRSA(row).then(res => {
        tabState.confirmLoading = false;
        if (res.code === RESULT_CODE_SUCCESS) {
          message.success(t('common.operateOk'), 3);
        } else {
          message.error(t('common.operateErr'), 3);
        }
      });
    },
  });
}

/**
 * 表单修改网元类型
 */
function fnNeTypeChange(v: any, data: any) {
  // 网元默认只含22和4100
  if (modalState.from.hosts.length === 3) {
    modalState.from.hosts.pop();
  }
  const hostsLen = modalState.from.hosts.length;
  // UPF标准版本可支持5002
  if (hostsLen === 2 && v === 'UPF') {
    modalState.from.hosts.push({
      id: undefined,
      hostType: 'telnet',
      groupId: '1',
      title: 'Telnet_NE_5002',
      addr: modalState.from.ip,
      port: 5002,
      user: 'admin',
      authMode: '0',
      password: 'admin',
      remark: '',
    });
  }
  // UDM可支持6379
  if (hostsLen === 2 && v === 'UDM') {
    modalState.from.hosts.push({
      id: undefined,
      hostType: 'redis',
      groupId: '1',
      title: 'REDIS_NE_6379',
      addr: modalState.from.ip,
      port: 6379,
      user: 'udmdb',
      authMode: '0',
      password: 'helloearth',
      dbName: '0',
      remark: '',
    });
  }
}

//打开新增或修改界面
function fnModalVisibleByEdit(record?: any) {
  if (!record) {
    //modalStateFrom.resetFields();
    modalState.title = t('views.ne.neInfo.addTitle');
    const neId = `${new Date().getMilliseconds()}`.padStart(3, '0');
    modalState.from = {
      id: undefined,
      neId: neId,
      neType: '',
      neName: `New_${neId}`,
      ip: '',
      port: 33030,
      pvFlag: 'PNF',
      rmUid: `4400HXNew${neId}`,
      neAddress: '',
      dn: '-',
      vendorName: '-',
      province: 'Area',
      // 主机
      hosts: [
        {
          id: undefined,
          hostType: 'ssh',
          groupId: '1',
          title: 'SSH_NE_22',
          addr: '',
          port: 22,
          user: 'omcuser',
          authMode: '2',
          password: '',
          privateKey: '',
          passPhrase: '',
          remark: '',
        },
        {
          id: undefined,
          hostType: 'telnet',
          groupId: '1',
          title: 'Telnet_NE_4100',
          addr: '',
          port: 4100,
          user: 'admin',
          authMode: '0',
          password: 'admin',
          remark: '',
        },
      ],
    };
    modalState.openByEdit = true;
  } else {
    //获取单个网元信息 当修改时
    if (modalState.confirmLoading) return;
    const hide = message.loading(t('common.loading'), 0);
    modalState.confirmLoading = true;

    getNeInfo(record.id).then(res => {
      modalState.confirmLoading = false;
      hide();
      if (res.code === RESULT_CODE_SUCCESS) {
        Object.assign(modalState.from, res.data);
        modalState.title = t('views.ne.neInfo.editTitle');
        modalState.openByEdit = true;
      } else {
        message.error(t('common.getInfoFail'), 2);
      }
    });
  }
}

/**新增或修改网元 */
function fnModalOk() {
  modalState.confirmLoading = true;
  const from = toRaw(modalState.from);
  from.rmUid = `4400HX${from.neType}${from.neId}`; // 4400HX1AMF001
  from.neName = `${from.neType}_${from.neId}`; // AMF_001
  const result = from.id ? updateNeInfo(from) : addNeInfo(from);
  const hide = message.loading(t('common.loading'), 0);
  result
    .then(res => {
      if (res.code === RESULT_CODE_SUCCESS) {
        message.success({
          content: t('common.operateOk'),
          duration: 3,
        });
        fnGetList();
      } else {
        message.error({
          content: `${res.msg}`,
          duration: 3,
        });
      }
    })
    .finally(() => {
      hide();
      fnModalCancel();
    });
}

/**
 * 删除网元
 * @param data 当前选项的data
 */
function fnDelete(data: any) {
  Modal.confirm({
    title: t('common.tipTitle'),
    content: `${data.neName} ${t('views.ne.neInfo.delTip')}`,
    onOk() {
      tableState.loading = true;
      const hide = message.loading(t('common.loading'), 0);
      delNeInfo(data.id)
        .then(res => {
          if (res.code === RESULT_CODE_SUCCESS) {
            message.success(t('common.operateOk'), 3);
            tableState.loading = false;
            fnGetList();
          } else {
            message.error({
              content: `${res.msg}`,
              duration: 3,
            });
          }
        })
        .finally(() => {
          hide();
          tableState.loading = false;
        });
    },
  });
}

/**
 * 对话框弹出关闭执行函数
 * 进行表达规则校验
 */
function fnModalCancel() {
  modalState.openByEdit = false;
  modalState.confirmLoading = false;
  tabState.confirmLoading = false;
}

/**
 * 表单修改网元IP
 */
function fnNeIPChange(e: any, data: any) {
  const v = e.target.value;
  if (v.length < 7) return; //IP地址长度
  //主机host数组addr都置成e.target.value
  for (const host of data.hosts) {
    host.addr = v;
  }
}

/**表单验证IP地址是否有效 */
function modalStateFromEqualIPV4AndIPV6(
  rule: Record<string, any>,
  value: string,
  callback: (error?: string) => void
) {
  if (!value) {
    return Promise.reject(t('views.ne.common.ipAddrPlease'));
  }

  if (value.indexOf('.') === -1 && value.indexOf(':') === -1) {
    return Promise.reject(t('valid.ipPlease'));
  }
  if (value.indexOf('.') !== -1 && !regExpIPv4.test(value)) {
    return Promise.reject(t('valid.ipv4Reg'));
  }
  if (value.indexOf(':') !== -1 && !regExpIPv6.test(value)) {
    return Promise.reject(t('valid.ipv6Reg'));
  }
  return Promise.resolve();
}

/**返回上一步 */
function fnStepPrev() {
  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.system.quickStart.stepNeInfoStepPrev'),
    onOk() {
      fnToStepName('SystemConfig');
    },
  });
}

/**下一步操作 */
function fnStepNext(stepName: 'NeInfoConfigPara5G') {
  if (stepName === 'NeInfoConfigPara5G') {
    Modal.confirm({
      title: t('common.tipTitle'),
      content: t('views.system.quickStart.stepNeInfoStepNext'),
      onOk() {
        fnToStepName('NeInfoConfigPara5G');
      },
    });
  }
}

const editableData: any = reactive({});
const inputField = ref<HTMLInputElement | null>(null); // 定义输入框的 ref

//可编辑行
function edit(key: string) {
  // 查找相关的项
  const itemToEdit = tabState.panes.find((item: any) => key === item.key);
  editableData[key] = { ...itemToEdit };

  //聚焦input框
  nextTick(() => {
    if (inputField.value) {
      inputField.value.focus();
    }
  });
}

//脱离input框时即保存
function save(key: string) {
  const from = toRaw(tabState.panes.filter((item: any) => key === item.key)[0]);
  if (editableData[key].ip !== from.ip) {
    const fromData = Object.assign(from, editableData[key]);

    //同步hosts下addr
    for (const host of fromData.hosts) {
      host.addr = fromData.ip;
    }

    updateNeInfo(fromData)
      .then(res => {
        if (res.code === RESULT_CODE_SUCCESS) {
          message.success({
            content: t('common.operateOk'),
            duration: 3,
          });
          fnGetList();
        } else {
          message.error({
            content: `${res.msg}`,
            duration: 3,
          });
        }
      })
      .finally(() => {
        fnModalCancel();
      });
  }
  //退出编辑框
  delete editableData[key];
}

/**获取列表 */
function fnGetList() {
  listAllNeInfo({
    bandHost: true,
  }).then(res => {
    if (res.code === RESULT_CODE_SUCCESS) {
      tabState.panes = [];
      res.data.forEach((item: any, index: any) => {
        if (item.neType === 'OMC' || !Array.isArray(item.hosts)) return;
        item.key = index + 1;
        tabState.panes.push(item);
      });
    }
  });
}

//
onMounted(() => {
  // 初始字典数据
  Promise.allSettled([
    getDict('ne_host_type'),
    getDict('ne_host_groupId'),
    getDict('ne_host_authMode'),
  ])
    .then(resArr => {
      if (resArr[0].status === 'fulfilled') {
        dict.neHostType = resArr[0].value;
      }
      if (resArr[1].status === 'fulfilled') {
        dict.neHostGroupId = resArr[1].value;
      }
      if (resArr[2].status === 'fulfilled') {
        dict.neHostAuthMode = resArr[2].value;
      }
    })
    .finally(() => {
      fnGetList();
    });
});
</script>

<template>
  <div class="ne">
    <a-table
      class="table"
      row-key="imsi"
      :columns="tableColumns"
      :loading="tableState.loading"
      :data-source="tabState.panes"
      :size="tableState.size"
      :pagination="false"
      :scroll="{ y: 'calc(100vh - 480px)' }"
      @resizeColumn="(w:number, col:any) => (col.width = w)"
    >
      <template #bodyCell="{ column, text, record }">
        <template v-if="column.key === 'operation'">
          <a-space :size="8" align="center">
            <a-tooltip>
              <template #title>{{ t('common.editText') }}</template>
              <a-button
                type="link"
                @click.prevent="fnModalVisibleByEdit(record)"
              >
                <template #icon>
                  <FormOutlined />
                </template>
              </a-button>
            </a-tooltip>
            <a-tooltip>
              <template #title> {{ t('common.deleteText') }}</template>
              <a-button type="link" @click.prevent="fnDelete(record)">
                <template #icon>
                  <delete-outlined />
                </template>
              </a-button>
            </a-tooltip>
          </a-space>
        </template>
        <template v-if="column.dataIndex === 'ip'">
          <div class="editable-cell">
            <div
              v-if="editableData[record.key]"
              class="editable-cell-input-wrapper"
            >
              <a-input
                ref="inputField"
                v-model:value="editableData[record.key].ip"
                @blur="save(record.key)"
              />
            </div>
            <div
              v-else
              class="editable-cell-text-wrapper"
              @dblclick="edit(record.key)"
            >
              {{ text || ' ' }}
              <edit-outlined
                class="editable-cell-icon"
                @click="edit(record.key)"
              />
            </div>
          </div>
        </template>
      </template>
    </a-table>

    <div class="ne-oper">
      <a-space direction="horizontal" :size="18">
        <a-button @click="fnStepPrev()" :disabled="tabState.confirmLoading">
          {{ t('views.system.quickStart.exit') }}
        </a-button>
        <!-- 添加网元 -->
        <a-button type="primary" ghost @click.prevent="fnModalVisibleByEdit()">
          <template #icon><PlusOutlined /></template>
          {{ t('common.addText') }}
        </a-button>

        <a-button
          type="primary"
          @click="fnStepNext('NeInfoConfigPara5G')"
          :loading="tabState.confirmLoading"
        >
          {{ t('views.system.quickStart.stepNext') }}
        </a-button>
      </a-space>
    </div>
  </div>
  <!-- 新增框或修改框 -->
  <ProModal
    :drag="true"
    :width="800"
    :destroyOnClose="true"
    :keyboard="false"
    :mask-closable="false"
    :open="modalState.openByEdit"
    :title="modalState.title"
    :confirm-loading="modalState.confirmLoading"
    @ok="fnModalOk"
    @cancel="fnModalCancel"
  >
    <a-form
      name="modalStateFrom"
      layout="horizontal"
      :label-col="{ span: 6 }"
      :labelWrap="true"
      :model="modalState.from"
      autocomplete="off"
    >
      <a-row>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.ne.common.neType')"
            name="neType"
            :rules="{
              required: true,
              message: t('views.ne.common.neTypePlease'),
            }"
          >
            <a-auto-complete
              v-model:value="modalState.from.neType"
              :options="
                NE_TYPE_LIST.filter(s => s !== 'OMC').map(v => ({
                  value: v,
                }))
              "
              @change="(v:any) => fnNeTypeChange(v, modalState.from)"
            >
              <a-input
                allow-clear
                :placeholder="t('views.ne.common.neTypePlease')"
                :maxlength="32"
              >
                <template #prefix>
                  <a-tooltip placement="topLeft">
                    <template #title>
                      {{ t('views.ne.common.neTypeTip') }}
                    </template>
                    <InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
                  </a-tooltip>
                </template>
              </a-input>
            </a-auto-complete>
          </a-form-item>
        </a-col>

        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.ne.common.neId')"
            name="neId"
            :rules="{
              required: true,
              message: t('views.ne.common.neIdPlease'),
            }"
          >
            <a-input
              v-model:value="modalState.from.neId"
              allow-clear
              :placeholder="t('views.ne.common.neIdPlease')"
              :maxlength="24"
            >
              <template #prefix>
                <a-tooltip placement="topLeft">
                  <template #title>
                    {{ t('views.ne.common.neIdTip') }}
                  </template>
                  <InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
                </a-tooltip>
              </template>
            </a-input>
          </a-form-item>
        </a-col>
      </a-row>

      <a-row>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.ne.common.ipAddr')"
            name="ip"
            :rules="[
              {
                required: true,
              },
              {
                validator: modalStateFromEqualIPV4AndIPV6,
              },
            ]"
          >
            <a-input
              v-model:value="modalState.from.ip"
              allow-clear
              :placeholder="t('views.ne.common.ipAddrPlease')"
              :maxlength="128"
              @change="(e:any) => fnNeIPChange(e, modalState.from)"
            >
              <template #prefix>
                <a-tooltip placement="topLeft">
                  <template #title>
                    <div>
                      {{ t('views.ne.common.ipAddrTip') }}
                    </div>
                  </template>
                  <InfoCircleOutlined style="opacity: 0.45; color: inherit;" />
                </a-tooltip>
              </template>
            </a-input>
          </a-form-item>
        </a-col>
        <a-col :lg="12" :md="12" :xs="24"> </a-col>
      </a-row>

      <template v-if="modalState.from.hosts.length > 0">
        <a-divider orientation="left">
          {{ t('views.ne.neInfo.hostConfig') }}
        </a-divider>

        <!-- 主机连接配置 -->
        <a-row>
          <a-col :lg="12" :md="12" :xs="24">
            <a-form-item :label="t('views.ne.neHost.addr')">
              <a-input
                v-model:value="modalState.from.hosts[0].addr"
                allow-clear
                :maxlength="128"
                :placeholder="t('common.inputPlease')"
              >
              </a-input>
            </a-form-item>
          </a-col>
          <a-col :lg="12" :md="12" :xs="24">
            <a-form-item :label="t('views.ne.neHost.port')" name="port">
              <a-input-number
                v-model:value="modalState.from.hosts[0].port"
                :min="10"
                :max="65535"
                :step="1"
                :maxlength="5"
                :placeholder="t('common.inputPlease')"
                style="width: 100%"
              ></a-input-number>
            </a-form-item>
          </a-col>
        </a-row>

        <a-row>
          <a-col :lg="12" :md="12" :xs="24">
            <a-form-item :label="t('views.ne.neHost.user')">
              <a-input
                v-model:value="modalState.from.hosts[0].user"
                allow-clear
                :maxlength="32"
                :placeholder="t('common.inputPlease')"
              >
              </a-input>
            </a-form-item>
          </a-col>
          <a-col :lg="12" :md="12" :xs="24">
            <a-form-item :label="t('views.ne.neHost.authMode')">
              <a-select
                v-model:value="modalState.from.hosts[0].authMode"
                default-value="0"
                :options="dict.neHostAuthMode"
              >
              </a-select>
            </a-form-item>
          </a-col>
        </a-row>

        <a-form-item
          v-if="modalState.from.hosts[0].authMode === '0'"
          :label="t('views.ne.neHost.password')"
          :label-col="{ span: 3 }"
          :label-wrap="true"
        >
          <a-input-password
            v-model:value="modalState.from.hosts[0].password"
            :maxlength="128"
            :placeholder="t('common.inputPlease')"
          >
          </a-input-password>
        </a-form-item>

        <template v-if="modalState.from.hosts[0].authMode === '1'">
          <a-form-item
            :label="t('views.ne.neHost.privateKey')"
            :label-col="{ span: 3 }"
            :label-wrap="true"
          >
            <a-textarea
              v-model:value="modalState.from.hosts[0].privateKey"
              :auto-size="{ minRows: 4, maxRows: 6 }"
              :maxlength="3000"
              :show-count="true"
              :placeholder="t('views.ne.neHost.privateKeyPlease')"
            />
          </a-form-item>

          <a-form-item
            :label="t('views.ne.neHost.passPhrase')"
            :label-col="{ span: 3 }"
            :label-wrap="true"
          >
            <a-input-password
              v-model:value="modalState.from.hosts[0].passPhrase"
              :maxlength="128"
              :placeholder="t('common.inputPlease')"
            >
            </a-input-password>
          </a-form-item>
        </template>

        <a-form-item
          :label="t('views.ne.neHost.test')"
          name="test"
          :label-col="{ span: 3 }"
          :label-wrap="true"
        >
          <a-button
            type="dashed"
            shape="round"
            @click="fnHostTest(modalState.from.hosts[0])"
            :disabled="tabState.confirmLoading"
          >
            <template #icon><LinkOutlined /></template>
          </a-button>

          <a-button
            type="link"
            @click="fnHostAuthorized(modalState.from.hosts[0])"
            :disabled="tabState.confirmLoading"
            v-if="
              modalState.from.hosts[0].hostType === 'ssh' &&
              modalState.from.hosts[0].authMode !== '2'
            "
          >
            {{ t('views.ne.neHost.authRSA') }}
          </a-button>
        </a-form-item>
      </template>

      <!-- <a-form-item :wrapper-col="{ offset: 10, span: 4 }">
              <a-button
                type="primary"
                ghost
                html-type="submit"
                :disabled="tabState.confirmLoading"
              >
                {{ t('views.system.quickStart.save') }}
              </a-button>
            </a-form-item> -->
    </a-form>
  </ProModal>
</template>

<style lang="less" scoped>
.neinfo-tabs :deep(.ant-tabs-tabpane) {
  padding: 24px;
  height: 60vh;
  overflow-y: auto;
  overflow-x: hidden;
  // margin-bottom: 24px;
  // margin-top: 24px;
}

.ne {
  padding-top: 12px;
  // height: 78vh;
  overflow-x: hidden;
  overflow-y: auto;

  &-oper {
    padding-top: 24px;
    text-align: end;
  }
}

.editable-cell {
  position: relative;
  .editable-cell-input-wrapper,
  .editable-cell-text-wrapper {
    padding-right: 24px;
  }

  .editable-cell-text-wrapper {
    padding: 5px 24px 5px 5px;
  }

  .editable-cell-icon,
  .editable-cell-icon-check {
    position: absolute;
    right: 0;
    width: 20px;
    cursor: pointer;
  }

  .editable-cell-icon {
    margin-top: 4px;
    display: none;
  }

  .editable-cell-icon-check {
    line-height: 28px;
  }

  .editable-cell-icon:hover,
  .editable-cell-icon-check:hover {
    color: #108ee9;
  }

  .editable-add-btn {
    margin-bottom: 8px;
  }
}
.editable-cell:hover .editable-cell-icon {
  display: inline-block;
}
</style>
