<script setup lang="ts">
import { computed, onMounted, reactive, ref, useTemplateRef } from 'vue';
import { message, Modal } from 'ant-design-vue';

import ModalGuidance from '@/layout/ModalGuidance.vue';
import SvgIcon from '@/components/SvgIcon.vue';
import { useRequest } from '@/hooks/request';
import { useViewVisible } from '@/hooks/view-visible';
import { t } from '@/i18n';
import { deleteProtocolBaseInfo, getProtocolList, updateProtocolBaseInfo } from '@/api';

import ProtocolContent from '../setup-protocol/ProtocolContent.vue';
import SetupProtocol from '../setup-protocol/SetupProtocol.vue';

import type { ColumnType } from 'ant-design-vue/es/table';
import type { PageParams, ProtocolBaseInfo } from '@/types';

const protocolInitialInfo: Partial<ProtocolBaseInfo> = {
  id: undefined,
  protocolName: '',
  protocolType: undefined,
  deviceType: undefined,
  dataBit: 5,
  parityBit: 'N',
  stopBit: '1',
  baudRate: undefined,
  dataSendInterval: undefined,
  highFreqSendInterval: undefined,
  readTimeout: undefined,
  nextDataReadDelay: undefined,
  nextRoundDataReadDelay: undefined,
  readContinuousAddr: undefined,
  readContinuousAddrCode: undefined,
  readContinuousAddrLength: undefined,
  byteOrder: undefined,
  byteOrderCode: undefined,
  addrOrder: undefined,
  addrOrderCode: undefined,
};

const protocolInfoForm = reactive<Partial<ProtocolBaseInfo>>({
  ...protocolInitialInfo,
});

const protocolList = ref<ProtocolBaseInfo[]>([]);
const protocolTotal = ref(0);
const searchContent = ref('');
const pageParams = ref<PageParams>({
  pageIndex: 1,
  pageSize: 10,
  pageSorts: [
    {
      column: 'id',
      asc: true,
    },
  ],
});

const columns = computed<ColumnType<ProtocolBaseInfo>[]>(() => {
  return [
    {
      title: t('gatewayProtocol.protocolName'),
      dataIndex: 'protocolName',
      key: 'protocolName',
    },
    {
      title: t('setupProtocol.protocolType'),
      dataIndex: 'protocolType',
      key: 'protocolType',
    },
    {
      title: t('setupProtocol.deviceType'),
      dataIndex: 'deviceType',
      key: 'deviceType',
    },
    {
      title: t('common.updateTime'),
      dataIndex: 'updateTime',
      key: 'updateTime',
    },
    {
      title: t('common.operation'),
      key: 'action',
    },
  ];
});

onMounted(() => {
  getProtocolData();
});

const { isLoading, handleRequest } = useRequest();

const getProtocolData = () => {
  handleRequest(async () => {
    const { records, total } = await getProtocolList({
      ...pageParams.value,
      searchContent: searchContent.value,
    });

    protocolList.value = records;
    protocolTotal.value = total;
  });
};

const handleSearch = () => {
  pageParams.value.pageIndex = 1;
  getProtocolData();
};

const handleAdd = () => {
  modalGuidanceRef.value?.showView();
};

const handleEdit = (record: ProtocolBaseInfo) => {
  Object.assign(protocolInfoForm, record);
  showView();
};

const handleDelete = (record: ProtocolBaseInfo) => {
  Modal.confirm({
    title: t('gatewayProtocol.confirmDeleteProtocol', { name: record.protocolName }),
    async onOk() {
      try {
        await deleteProtocolBaseInfo(record.id);
        message.success(t('gatewayProtocol.deleteProtocolSuccessful'));
        pageParams.value.pageIndex = 1;
        getProtocolData();
      } catch (err) {
        message.error((err as Error).message);
        console.error(err);
      }
    },
  });
};

const handlePageChange = (page: number, pageSize: number) => {
  pageParams.value.pageIndex = page;
  pageParams.value.pageSize = pageSize;
  getProtocolData();
};

const modalGuidanceRef = useTemplateRef('modalGuidance');

const { isLoading: isConfirmLoading, handleRequest: handleModalConfirmRequest } = useRequest();
const { visible, showView, hideView } = useViewVisible();
const protocolContentRef = useTemplateRef('protocolContent');

const handleClose = () => {
  Object.assign(protocolInfoForm, protocolInitialInfo);
};

const handleOk = () => {
  handleModalConfirmRequest(async () => {
    await protocolContentRef.value?.validateProtocolInfo();
    await protocolContentRef.value?.isAtLeastOneParam();
    await updateProtocolBaseInfo(protocolInfoForm);
    message.success(t('gatewayProtocol.editProtocolSuccessful'));
    getProtocolData();
    hideView();
  });
};
</script>

<template>
  <div class="protocol-list-container">
    <div class="protocol-search">
      <div>
        <span class="protocol-search-label">{{ $t('common.search') }}:</span>
        <AInput
          v-model:value="searchContent"
          class="protocol-search-input"
          :placeholder="$t('gatewayProtocol.searchTip')"
          allow-clear
        />
      </div>
      <AButton type="primary" @click="handleSearch">{{ $t('common.query') }}</AButton>
    </div>
    <div class="protocol-add-container">
      <AButton class="icon-button add-button" type="primary" @click="handleAdd">
        <SvgIcon name="plus" />
        {{ $t('common.addNew') }}
      </AButton>
    </div>
    <ATable
      class="protocol-table"
      :data-source="protocolList"
      :columns="columns"
      row-key="id"
      :loading="isLoading"
      :pagination="{
        current: pageParams.pageIndex,
        pageSize: pageParams.pageSize,
        total: protocolTotal,
        showSizeChanger: false,
        hideOnSinglePage: false,
        onChange: handlePageChange,
      }"
    >
      <template #bodyCell="{ column, record }">
        <span v-if="column.key === 'action'">
          <a @click="handleEdit(record as ProtocolBaseInfo)">{{ $t('common.revise') }}</a>
          <ADivider type="vertical" />
          <a @click="handleDelete(record as ProtocolBaseInfo)">{{ $t('common.delete') }}</a>
        </span>
      </template>
    </ATable>
    <ModalGuidance ref="modalGuidance" @finish="getProtocolData">
      <SetupProtocol />
    </ModalGuidance>
    <AModal
      v-model:open="visible"
      wrap-class-name="gateway-protocol-modal"
      :title="$t('common.editor')"
      :width="1140"
      centered
      :mask-closable="false"
      :after-close="handleClose"
      :confirm-loading="isConfirmLoading"
      destroy-on-close
      @ok="handleOk"
    >
      <ProtocolContent ref="protocolContent" :info="protocolInfoForm" :is-recognized="false" />
    </AModal>
  </div>
</template>

<style lang="scss">
.gateway-protocol-modal {
  .ant-modal-content {
    height: 638px;
  }

  .ant-modal-body {
    height: calc(100% - 84px);
    overflow: hidden auto;
  }
}
</style>

<style lang="scss" scoped>
.protocol-list-container {
  height: 100%;
  padding: 32px;
  background: var(--antd-color-bg-base);
  border-radius: 18px;
}

.protocol-search {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
}

.protocol-search-label {
  margin-right: 10px;
  font-size: 14px;
  line-height: 22px;
  color: var(--antd-color-text);
}

.protocol-search-input {
  width: 272px;
}

.protocol-add-container {
  display: flex;
  align-items: center;
}

.add-button {
  margin-right: 8px;
  font-size: 14px;
}

.protocol-table {
  margin-top: 72px;

  a {
    color: var(--antd-color-primary);
  }
}
</style>
