<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 { useUserInfoStore } from '@/stores/user-info';
import { t } from '@/i18n';
import { deleteProtocolBaseInfo, getProtocolList, updateProtocolBaseInfo } from '@/api';
import { getTablePageSorts } from '@/utils';
import { OperatePermission } from '@/utils/permission-type';

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

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

const { booleanPermission } = useUserInfoStore();
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: '关',
  readContinuousAddrCode: 0,
  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',
      sorter: true,
    },
    {
      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,
      isDraft: 0,
    });

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

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

const handleReset = () => {
  searchContent.value = '';
  handleSearch();
};

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 handleProtocolTableChange: TableProps['onChange'] = (pagination, filters, sorter) => {
  pageParams.value.pageIndex = pagination.current || 1;
  pageParams.value.pageSize = pagination.pageSize || 10;
  pageParams.value.pageSorts = getTablePageSorts(sorter);
  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>
  <AFlex justify="space-between">
    <div class="hvac-layout-main-title">{{ $t('navigation.protocolManage') }}</div>
    <AButton
      class="icon-button add-button"
      type="primary"
      @click="handleAdd"
      v-if="booleanPermission(OperatePermission.新增协议)"
    >
      <SvgIcon name="plus" />
      {{ $t('common.addNew') }}
    </AButton>
  </AFlex>
  <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>
      <div>
        <AButton type="primary" @click="handleSearch">{{ $t('common.query') }}</AButton>
        <AButton @click="handleReset">{{ $t('common.reset') }}</AButton>
      </div>
    </div>
    <ATable
      class="hvac-table protocol-table"
      :data-source="protocolList"
      :columns="columns"
      row-key="id"
      :loading="isLoading"
      :pagination="{
        current: pageParams.pageIndex,
        pageSize: pageParams.pageSize,
        total: protocolTotal,
        showSizeChanger: true,
        showQuickJumper: true,
        hideOnSinglePage: false,
        showTotal: (total) => $t('common.pageTotal', { total }),
      }"
      @change="handleProtocolTableChange"
    >
      <template #bodyCell="{ column, record }">
        <span v-if="column.key === 'action'">
          <SvgIcon
            v-if="booleanPermission(OperatePermission.编辑协议)"
            class="action-icon"
            name="edit-o"
            @click="handleEdit(record as ProtocolBaseInfo)"
          />
          <SvgIcon
            v-if="booleanPermission(OperatePermission.删除协议)"
            class="action-icon"
            name="delete"
            @click="handleDelete(record as ProtocolBaseInfo)"
          />
        </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" disabled-form />
    </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 {
  padding: 24px;
  margin-top: 16px;
  background: var(--antd-color-bg-base);
  border-radius: 16px;
}

.protocol-search {
  display: flex;
  align-items: center;
  justify-content: space-between;

  button + button {
    margin-left: 12px;
  }
}

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

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

.add-button {
  width: 84px;
  font-size: 14px;
}

.protocol-table {
  margin-top: 16px;
}

.action-icon {
  margin-right: 16px;
  font-size: 24px;
  color: var(--antd-color-primary);
  cursor: pointer;
}
</style>
