<script setup lang="ts">
import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { DataPushRule } from '#/api-client';

import { h, nextTick, ref } from 'vue';
import { useRouter } from 'vue-router';

import { Page, useVbenModal } from '@vben/common-ui';

import { message as Message, Tag } from 'ant-design-vue';

import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
  postAggregationIoTplatformUpdateIoTplatformProductThingModelInfoAsync,
  postFilesDownload,
  postFilesUpload,
  postOneNetProductDeleteAsync,
  postOneNetProductInsertAsync,
  postOneNetProductListAsync,
  postOneNetProductModifyAsync,
  postOneNetProductOneNetDataFlowConfig,
  postOneNetProductProductStatusChangeAsync,
} from '#/api-client';
import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import DataPushRuleEditor from '#/views/components/DataPushRuleEditor.vue';

import {
  addProductFormSchema,
  editProductFormSchemaEdit,
  querySchema,
  setFileSelectedCallback,
  tableSchema,
} from './schema';

defineOptions({
  name: 'OneNETProduct',
});

const router = useRouter();
const formOptions: VbenFormProps = {
  schema: querySchema.value,
};
const gridOptions: VxeGridProps<any> = {
  checkboxConfig: {
    highlight: true,
    labelField: 'name',
  },
  columns: tableSchema.value,
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  toolbarConfig: {
    custom: true,
  },
  customConfig: {
    storage: true,
  },
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues) => {
        const { data } = await postOneNetProductListAsync({
          body: {
            pageIndex: page.currentPage,
            pageSize: page.pageSize,
            ...formValues,
          },
        });
        return data;
      },
    },
  },
};

const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });

const editRow: Record<string, any> = ref({});
// 产品数据流转规则集合（多规则编辑器 v-model）
const dataFlowRules = ref<DataPushRule[]>([]);
// 声明文件变量，用于存储选择的文件
let selectedFile: File | null = null;
// 物模型更新 loading 状态，使用对象存储每行的 loading 状态
const thingModelUpdateLoading = ref<Record<string, boolean>>({});

// 设置文件选择回调
setFileSelectedCallback((file) => {
  selectedFile = file;
});
const [UserModal, userModalApi] = useVbenModal({
  draggable: true,
  footer: true,
  showCancelButton: true,
  showConfirmButton: true,
  onConfirm: submit,
  onBeforeClose: () => {
    // 只在确认提交后重置，而不是每次关闭都重置
    return true;
  },
  onOpen: () => {
    // 重置文件选择
    selectedFile = null;
  },
  onOpenChange: (isOpen: boolean) => {
    if (isOpen && editRow.value.id) {
      // 编辑模式下，模态框打开后设置表单值
      nextTick(() => {
        editFormApi.setValues({ ...editRow.value });
      });
    }
  },
  onCancel: () => {
    // 取消时也重置文件选择
    selectedFile = null;
    // 关闭模态框
    userModalApi.close();
  },
});

const [AddForm, addFormApi] = useVbenForm({
  // 默认展开
  collapsed: false,
  // 所有表单项共用，可单独在表单内覆盖
  commonConfig: {
    labelWidth: 110,
    componentProps: {
      class: 'w-4/5',
    },
  },
  layout: 'horizontal',
  schema: addProductFormSchema.value,
  showCollapseButton: false,
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2',
});

const [EditForm, editFormApi] = useVbenForm({
  // 默认展开
  collapsed: false,
  // 所有表单项共用，可单独在表单内覆盖
  commonConfig: {
    labelWidth: 110,
    componentProps: {
      class: 'w-4/5',
    },
  },
  // 提交函数
  layout: 'horizontal',
  schema: editProductFormSchemaEdit.value,
  showCollapseButton: false,
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2',
});

const [DataFlowForm, dataFlowFormApi] = useVbenForm({
  // 默认展开
  collapsed: false,
  // 与产品新增表单保持一致的布局和宽度
  commonConfig: {
    labelWidth: 120,
    componentProps: {
      class: 'w-4/5',
    },
  },
  layout: 'horizontal',
  showCollapseButton: false,
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2',
  schema: [
    {
      component: 'Switch',
      fieldName: 'isNeedPushData',
      label: '是否推送数据',
      componentProps: {
        checkedValue: true,
        unCheckedValue: false,
        checkedChildren: '是',
        unCheckedChildren: '否',
        // 覆盖公共宽度样式，避免开关被拉长
        class: 'ml-6',
      },
    },
  ],
});

const [DataFlowModal, dataFlowModalApi] = useVbenModal({
  draggable: true,
  footer: true,
  showCancelButton: true,
  showConfirmButton: true,
  onConfirm: submitDataFlowConfig,
});

// 新增和编辑提交的逻辑
async function submit() {
  const isEdit = !!editRow.value.id;
  const formApi = isEdit ? editFormApi : addFormApi;
  const api = isEdit
    ? postOneNetProductModifyAsync
    : postOneNetProductInsertAsync;
  const { valid } = await formApi.validate();
  if (!valid) return;

  const formValues = await formApi.getValues();

  // 提交前校验
  if (!formValues.thingModelFileName) {
    Message.error('请选择设备模型文件');
    return;
  }

  // 如果有文件需要上传，先上传
  if (selectedFile) {
    try {
      userModalApi.setState({ loading: true, confirmLoading: true });
      const result = await postFilesUpload({ body: { files: [selectedFile] } });
      if (result.status === 204 || result.status === 200) {
        const fileInfo = result.data?.[0];
        if (fileInfo && fileInfo.id) {
          formValues.deviceThingModelFileId = fileInfo.id;
          // 设置文件名
          formValues.thingModelFileName =
            fileInfo.fileName || selectedFile.name;
        } else {
          Message.error('文件上传成功但未获取到文件ID');
          userModalApi.setState({ loading: false, confirmLoading: false });
          return;
        }
      } else {
        Message.error('文件上传失败');
        userModalApi.setState({ loading: false, confirmLoading: false });
        return;
      }
    } catch {
      Message.error('文件上传失败');
      userModalApi.setState({ loading: false, confirmLoading: false });
      return;
    }
  }

  // 清空全局变量，防止下次误用
  selectedFile = null;

  // 继续后续表单提交逻辑

  const fetchParams: any = isEdit
    ? {
      id: editRow.value.id,
      ...formValues,
    }
    : {
      ...formValues,
    };

  try {
    const resp = await api({ body: fetchParams });
    if (resp.data) {
      Message.success(
        editRow.value.id ? $t('common.editSuccess') : $t('common.addSuccess'),
      );
      userModalApi.close();
      editRow.value = {};
      gridApi.reload();
    } else {
      Message.error(
        editRow.value.id ? $t('common.editFail') : $t('common.addFail'),
      );
    }
  } finally {
    userModalApi.setState({ loading: false, confirmLoading: false });
  }
}

async function onEdit(record: any) {
  editRow.value = record;
  userModalApi.open();
  // 重置文件选择状态
  selectedFile = null;
}

const openAddModal = async () => {
  editRow.value = {};
  userModalApi.open();
  // 重置文件选择状态
  selectedFile = null;
};

// 删除函数
async function onDel(record: any) {
  try {
    const resp = await postOneNetProductDeleteAsync({
      body: { id: record.id },
    });
    if (resp.data) {
      Message.success($t('common.deleteSuccess'));
      // 重置文件选择
      selectedFile = null;
      gridApi.reload();
    } else {
      Message.error($t('common.deleteFail'));
    }
  } catch {
    Message.error($t('common.deleteFail'));
  }
}

// 下载文件函数
async function onDownloadFile(record: any) {
  if (!record.deviceThingModelFileId) {
    Message.error('文件ID不存在，无法下载');
    return;
  }

  try {
    const { data } = await postFilesDownload({
      body: { id: record.deviceThingModelFileId },
      responseType: 'blob',
    });
    const url = window.URL.createObjectURL(new Blob([data as Blob]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute(
      'download',
      record.thingModelFileName || 'device-model-file',
    );
    document.body.append(link);
    link.click();
    link.remove();
    window.URL.revokeObjectURL(url);
    Message.success('文件下载成功');
  } catch {
    Message.error('文件下载失败');
  }
}

// 状态更改函数
async function onStatusChange(record: any) {
  try {
    const resp = await postOneNetProductProductStatusChangeAsync({
      body: {
        id: record.id,
        enabled: !record.isEnabled,
      },
    });
    if (resp.data) {
      Message.success(record.isEnabled ? '禁用成功' : '启用成功');
      gridApi.reload();
    } else {
      Message.error(record.isEnabled ? '禁用失败' : '启用失败');
    }
  } catch {
    Message.error(record.isEnabled ? '禁用失败' : '启用失败');
  }
}

async function onDataFlowConfig(record: any) {
  if (!record.id) {
    Message.error('产品数据ID不存在，无法进行数据流转配置');
    return;
  }

  // 记录当前行数据并打开数据流转配置弹窗
  editRow.value = record;
  dataFlowFormApi.setValues({
    isNeedPushData: record.isNeedPushData ?? false,
  });
  dataFlowRules.value = Array.isArray(record.dataPushRules)
    ? record.dataPushRules
    : [];
  dataFlowModalApi.open();
}

async function submitDataFlowConfig() {
  if (!editRow.value.id) {
    Message.error('产品数据ID不存在，无法进行数据流转配置');
    return;
  }

  const values = await dataFlowFormApi.getValues();
  const rules = dataFlowRules.value ?? [];

  // 开启推送时校验：至少一条规则，且启用的规则必须填服务地址与推送信息
  if (values.isNeedPushData) {
    if (rules.length === 0) {
      Message.error('请至少选择要推送的数据类型');
      return;
    }
    const invalid = rules.some(
      (r) => r.enabled && (!r.pushServer || !r.pushInfo),
    );
    if (invalid) {
      Message.error('启用的推送规则必须填写服务地址与推送路径/KEY');
      return;
    }
  }

  try {
    const resp = await postOneNetProductOneNetDataFlowConfig({
      body: {
        id: editRow.value.id,
        isNeedPushData: values.isNeedPushData ?? false,
        dataPushRules: rules,
      },
    });
    if (resp.data) {
      Message.success('数据流转配置成功');
      dataFlowModalApi.close();
      gridApi.reload();
    } else {
      Message.error('数据流转配置失败');
    }
  } catch {
    Message.error('数据流转配置失败');
  }
}

// 设备管理函数
function onDeviceManagement(record: any) {
  console.log('设备管理按钮被点击', record);
  // 跳转到设备管理页面，传递平台类型和平台产品ID作为参数
  router.push({
    path: '/devicemanagement/deviceinfo',
    query: {
      ioTPlatform: '2', // OneNET平台类型为2
      ioTPlatformProductId: record.ioTPlatformProductId, // 平台产品ID
      productName: record.productName,
    },
  });
}

// 物模型管理函数
function onThingModelManagement(record: any) {
  console.log('物模型管理按钮被点击', record);
  // 跳转到物模型管理页面，传递平台类型和平台产品ID作为参数
  router.push({
    path: '/thingmodelinfo/ioTPlatformThingModelInfo',
    query: {
      productId: record.ioTPlatformProductId, // 平台产品ID
      productName: record.productName,
      ioTPlatform: '2', // OneNET平台类型为2
    },
  });
}

// 获取行的操作按钮列表
function getRowActions(row: any) {
  const productId = row?.ioTPlatformProductId;
  return [
    {
      label: $t('common.edit'),
      type: 'link',
      size: 'small',
      auth: ['AbpIdentity.Users.Update'],
      onClick: onEdit.bind(null, row),
    },
    {
      label: $t('abp.deviceInfos.deviceInfoManage'),
      type: 'link',
      size: 'small',
      onClick: onDeviceManagement.bind(null, row),
    },
    {
      label: $t('abp.deviceInfos.thingModelInfoManage'),
      type: 'link',
      size: 'small',
      onClick: onThingModelManagement.bind(null, row),
    },
    {
      label: 'OneNET物模型更新',
      type: 'link',
      size: 'small',
      loading: productId
        ? thingModelUpdateLoading.value[productId] || false
        : false,
      onClick: onThingModelUpdate.bind(null, row),
    },
  ];
}

// 物模型更新函数
async function onThingModelUpdate(record: any) {
  const productId = record?.ioTPlatformProductId;
  if (!productId) {
    Message.error('产品ID不存在，无法更新物模型');
    return;
  }
  // 设置 loading 状态
  thingModelUpdateLoading.value = {
    ...thingModelUpdateLoading.value,
    [productId]: true,
  };
  try {
    const resp =
      await postAggregationIoTplatformUpdateIoTplatformProductThingModelInfoAsync(
        {
          body: {
            ioTPlatformType: 2, // OneNET 平台类型为 2
            ioTPlatformProductId: productId,
          },
        },
      );
    if (resp.data) {
      Message.success('物模型更新成功');
      gridApi.reload();
    } else {
      Message.error('物模型更新失败');
    }
  } catch (error) {
    console.error('物模型更新失败:', error);
    Message.error('物模型更新失败');
  } finally {
    // 清除 loading 状态
    thingModelUpdateLoading.value = {
      ...thingModelUpdateLoading.value,
      [productId]: false,
    };
  }
}
</script>

<template>
  <Page auto-content-height>
    <Grid>
      <template #toolbar-actions>
        <TableAction :actions="[
          {
            label: $t('common.add'),
            type: 'primary',
            icon: 'ant-design:plus-outlined',
            onClick: openAddModal.bind(null),
            auth: ['AbpIdentity.Users.Create'],
          },
        ]" />
      </template>

      <template #isEnable="{ row }">
        <component :is="h(Tag, { color: row.isEnabled ? 'green' : 'red' }, () =>
          row.isEnabled ? $t('common.yes') : $t('common.no'),
        )
          " />
      </template>

      <template #isNeedPushData="{ row }">
        <component :is="h(Tag, { color: row.isNeedPushData ? 'green' : 'red' }, () =>
          row.isNeedPushData ? $t('common.yes') : $t('common.no'),
        )
          " />
      </template>

      <template #thingModelFileName="{ row }">
        <a v-if="row.thingModelFileName && row.deviceThingModelFileId" @click="onDownloadFile(row)"
          style="color: #1890ff; text-decoration: underline; cursor: pointer">
          {{ row.thingModelFileName }}
        </a>
        <span v-else>{{ row.thingModelFileName || '-' }}</span>
      </template>

      <template #action="{ row }">
        <TableAction :actions="getRowActions(row)" :drop-down-actions="[
          {
            label: row.isEnabled
              ? $t('common.disabled')
              : $t('common.enabled'),
            icon: 'ant-design:edit-filled',
            type: 'primary',
            danger: row.isEnabled,
            size: 'small',
            auth: ['AbpIdentity.Users.Update'],
            popConfirm: {
              title: `确定要${row.isEnabled ? $t('common.disabled') : $t('common.enabled')
                }该产品吗？`,
              confirm: onStatusChange.bind(null, row),
            },
          },
          {
            label: '数据流转配置',
            icon: 'ant-design:setting-outlined',
            type: 'primary',
            size: 'small',
            onClick: onDataFlowConfig.bind(null, row),
          },
          {
            label: $t('common.delete'),
            icon: 'ant-design:delete-outlined',
            type: 'primary',
            popConfirm: {
              title: $t('common.askConfirmDelete'),
              confirm: onDel.bind(null, row),
            },
          },
        ]" />
      </template>
    </Grid>
    <UserModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
      <component :is="editRow.id ? EditForm : AddForm" />
    </UserModal>

    <DataFlowModal title="数据流转配置" class="w-[900px]">
      <DataFlowForm />
      <DataPushRuleEditor v-model:rules="dataFlowRules" />
    </DataFlowModal>
  </Page>
</template>
