import React, { useEffect, useRef, useState } from 'react';
import { CRUDProps, CRUDState } from '../../types';
import { LoadingOutlined } from '@ant-design/icons';
import { Icon } from '../../../../components/icons';
import { OfflineData, OfflineProps } from './types';
import { Button, Input, message, Modal, Progress, Spin } from 'antd';
import { ScanOutlined } from '@ant-design/icons';
import VirtualTable from '../../../../components/VirtualTable';
import { Shell } from '../../../../utils/shell';
import { Gzip, unGzip } from '../../../../utils/gzip';
import { tools } from '../../../../utils/shell/tools';
import { checkDuplicateKeys } from '../../../../utils/utils';
import { findDOMNode } from 'react-dom';
import { ActionSchema } from '../../../Action';
import { isMobile } from '../../../../utils/helper';
import { eventStation, RuleTypes } from '../../../../utils/shell/shell';
import { Drawer } from '../../../../components/antdComponentsProxy';
import { RFIDTrigeerCodeEnum, windowRFIDTriger } from '../../../../utils/RfidUtil';

const OfflineComponent: React.FC<OfflineProps> = (offlineProps) => {
  const { offlineSchema, render, env, aliasTitle, menuName, primaryField, name = '', offlineMode,
    store, filtercont, translate: __, classPrefix: ns, columns, tableLayout, search, curdRef
  } = offlineProps;
  
  const [offlineFormShow, setOfflineFormShow] = useState(false)
  const [position, setPosition] = useState({ x: document.body.clientWidth / 2 - 135, y: document.body.clientHeight - 200 })
  const [codeValue, setCodeValue] = useState('')
  const [offlineTemplist, setOfflineTemplist] = useState<string[]>([])
  const [offline, setOffline] = useState(false)
  const [offlineData, setOfflineData] = useState<obj[]>([])
  const [offlineColumns, setOfflineColumns] = useState<obj[]>([])
  const [codeVisible, setCodeVisible] = useState(false)
  const [currentRow, setCurrentRow] = useState<obj | null>(null)
  const [offlineLoading, setOfflineLoading] = useState(false)
  const [offlineStatus, setOfflineStatus] = useState(false)
  const [offlineProgress, setOfflineProgress] = useState(0)
  const positionX = useRef(0)
  const positionY = useRef(0)
  const offlineForm = useRef<HTMLDivElement | null>(null)
  const codeEvent = useRef<Function>();//红外线扫码
  const hashVal = useRef('')
  //离线的原始数据，用于重置按钮
  const originOfflineData = useRef<OfflineData[]>([])

  // 初始化逻辑
  useEffect(() => {
    windowRFIDTriger.addEventListener(RFIDTrigeerCodeEnum.TRIGGERCLICK, handleScanCode)
    if (Shell.hasShell() && isMobile()) {
      hashVal.current = window.location.hash.slice(1);
      codeEvent.current = eventStation.subscription<{ code: string; href: string }>(RuleTypes.ShellCode, ({ code, href }) => {
        if (hashVal.current == href) {
          scanCode(code)
        }
      })
      initOffline()
    }
    return () => {
      windowRFIDTriger.removeEventListener(RFIDTrigeerCodeEnum.TRIGGERCLICK, handleScanCode)
      codeEvent.current?.()
    }
  }, [])

  useEffect(() => {
    const tmp = localStorage.getItem('offlineTemplist')
    if (tmp) {
      const lastTmp = JSON.parse(tmp);
      !!lastTmp.length && setOfflineTemplist(lastTmp)
    }
  }, [])

  useEffect(() => {
    //存到本地以便下次进入时恢复临时数据
    localStorage.setItem('offlineTemplist', JSON.stringify(offlineTemplist))
    fixOfflineTmpList()
  }, [offlineTemplist])

  useEffect(() => {
    if(offlineMode) {
      handleClickOffline()
    }
  }, [offlineMode])

  useEffect(() => {
    if(!offlineLoading) {
      setOfflineProgress(0)
      setOfflineStatus(false)
    }
  }, [offlineLoading])

  //点击离线按钮，切换离线状态
  const handleClickOffline = async () => {
    const res = await hasDownload();
    setOfflineFormShow(true);
    initOfflineData(res);
  }

  const initOffline = async () => {
    const res = await hasDownload();
    if (!res) {
      await createTable()
    }
    if (offlineSchema.offlinePageType === 'detail') {
      setOfflineFormShow(true)
      initOfflineData(res)
    }
  }

  /**
   * 进入离线页面时初始化数据
   * @param hasDownload 是否已下载数据
   */
  const initOfflineData = (hasDownload: boolean) => {
    if (hasDownload) {
      Modal.confirm({
        content: '已有下载数据，是否重新下载？',
        okText: __('Offline.reload'),
        cancelText: __('Offline.continue'),
        onOk: async () => {
          await clear(name);
          setOfflineTemplist([]);
          download();
        },
        onCancel: () => {
          offlineOpt()
        }
      })
    } else {
      download()
    }
  }

  // 清空表中所有数据
  const clear = async (tableName: string): Promise<void> => {
    await Shell.execDelete(tableName);
    await Shell.deleteFile(tableName);
    return Promise.resolve();
  }

  // 模拟假的进度增长
  let offlineInterval: any = useRef();
  let offlineTimeout: any = useRef();
  const handleOfflineProgress = () => {
    offlineInterval.current = setInterval(() => {
      setOfflineProgress((prev) => prev + 4)
    }, 100);

    // 设置一个定时器，让进度条增长到 100 后停止
    offlineTimeout.current = setTimeout(() => {
      clearInterval(offlineInterval.current);
    }, 2400); // 毫秒后停止假的进度增长
  }

  //下载操作
  const download = () => {
    setOfflineLoading(true)
    setOfflineStatus(true)
    handleOfflineProgress();
    let params = {};
    if (Object.keys(filtercont || {}).length) {
      params = {
        advancedFilter: store.query?.advancedFilter,
        advancedHeader: store.query?.advancedHeader,
        advancedFilterSub: store.query?.advancedFilterSub
      }
      if (filtercont?.filterOptionData) {
        const { optionsParam } = filtercont?.filterOptionData;
        params = {
          ...params,
          ...optionsParam,
          filterParam: store.query?.filterParam
        }
      }
    }
    env.fetcher(offlineSchema.source, params).then(async res => {
      let tableData: OfflineData;
      if (!res.ok) {
        message.error(res.msg || '下载数据失败！');
        setOfflineLoading(false)
        setOfflineStatus(false)
        return false;
      }
      try {
        tableData = unGzip(res.data);
      } catch (error) {
        message.error('解压失败!')
        setOfflineLoading(false)
        setOfflineStatus(false)
        return false;
      }
      if (tools.isEmpty(tableData.offlineData)) {
        message.info('暂无数据可下载!')
        setOfflineLoading(false)
        setOfflineStatus(false)
        return false;
      }
      if (checkDuplicateKeys(tableData.offlineData.items, primaryField)) {
        message.warning('主键重复，请调整数据后重试！')
        setOfflineLoading(false)
        setOfflineStatus(false)
        return false;
      }
      /**终端下载资源包 */
      if (tableData.offlineZipResourceDown) {
        const { method, url, requestParam = {} } = tableData.offlineZipResourceDown
        const baseURL = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi || 'https://sasdev.sanfu.com/saas_dev';
        let downloadResult = await Shell.downloadImgZip(baseURL + url, method, JSON.stringify(requestParam));
        if (downloadResult.success === false) {
          message.error('下载资源包失败');
          setOfflineLoading(false)
          setOfflineStatus(false)
          return false;
        }
      }
      const result = await insertMany(name, tableData.offlineData.items, primaryField)
      if (!result) {
        message.error('数据插入失败，请检查数据！');
        return false;
      }
      clearInterval(offlineInterval.current)
      clearTimeout(offlineTimeout.current)
      setOfflineProgress(100)
      await offlineOpt()
      setOfflineLoading(false)
      setOfflineStatus(false)
      return;
    }).catch(async (err) => {
      //下载数据没数据，后端直接报错，那就执行这里，有坑
      console.error(err)
      try {
        await clear(name)
      } catch (error) {
        throw new Error(error)
      }
      setOfflineLoading(false)
      setOfflineStatus(false)
    })
  }
  //获取全部数据
  const findAll = async (tableName: string) => {
    if (Shell.hasShell()) {
      let res = await Shell.execFind(tableName)
      if (res.success) {
        var list = res?.data?.content ? JSON.parse(res.data.content) : [];
        return Promise.resolve(list)
      }
      if (res.success === false) {
        message.error(res.msg)
      }
    }
  }
  //创建数据库
  const createTable = async (): Promise<void> => {
    return new Promise(async (resolve, reject) => {
      try {
        await Shell.execCreateTable(name, primaryField)
        resolve()
      } catch (error) {
        console.error(error)
        reject()
      }
    })
  }
  //列转化
  const columnExchange = (col: any) => {
    let width = 0;
    // const hidePrimary = !columns.find((item: obj) => item.name === primaryField)
    if (tableLayout === 'horizontal') {
      const childList = curdRef?.current?.querySelector(`.${ns}Table-content`)?.getElementsByTagName('thead')[0].children[0].childNodes
      const index = columns.findIndex((item: obj) => item.name === col.name)
      width = (childList?.[index + 1] as HTMLDivElement)?.clientWidth || 0;
    } else {
      const childList = curdRef?.current?.querySelector(`.${ns}Table-content`)?.querySelector(`.${ns}Table-footTable`)?.getElementsByTagName('tbody')[0].childNodes
      const index = columns.findIndex((item: obj) => item.name === col.name)
      const thWidth = ((childList?.[index + 1] as HTMLDivElement)?.childNodes?.[0] as HTMLDivElement)?.clientWidth
      const tdWidth = ((childList?.[index + 1] as HTMLDivElement)?.childNodes?.[1] as HTMLDivElement)?.clientWidth
      width = thWidth > tdWidth ? thWidth : tdWidth
    }
    return {
      title: col.label,
      key: col.name,
      width: col.width || (width > 0 ? width + 10 : 100),
      dataIndex: col.name,
      align: col.align,
      ellipsis: true,
      cellClick: (record: obj) => {
        setCurrentRow(record)
        setOfflineFormShow(true)
        setOffline(false)
      },
      render: (text: any, record: obj, index: number) => {
        if (!text) {
          return <span className='text-muted'>-</span>
        }
        if (col.type === 'lion-upload') {
          return render('', { ...col, type: 'offline-image' }, {
            offlineData: text,
            offline: {
              tableName: name,
              primaryKey: primaryField,
              primaryValue: record?.[primaryField]
            }
          })
        }
        if (['radios', 'checkboxes', 'select'].includes(col.type)) {
          return text ? (text as string).split(',').map(data => {
            return col.options.find((item: obj) => item.value === data)?.label
          }).join(',') || text : <span className='text-muted'>-</span >
        }
        if (['select'].includes(col.type)) {
          return col.options?.find((data: obj) => data.value === text)?.label || text
        }
        if (col.type.includes('color')) {
          return render('', { ...col, type: 'color' }, { data: record, showValue: false })
        }
        if (col.type.includes('html')) {
          return text ? render('', { ...col, html: text }) : <span className='text-muted'>-</span >
        }
        if (col.type === 'textarea') {
          return render('', { ...col, label: null, type: 'tpl', defaultOpen: true }, { data: record })
        }
        if (['static-mapping'].includes(col.type)) {
          return text ? col.map?.[text] : <span className='text-muted'>-</span >
        }
        if (['input-date', 'input-datetime', 'input-time', 'input-month', 'input-quarter', 'input-year',
          'date', 'datetime', 'time', 'static-date', 'static-datetime', 'static-time'].includes(col.type)) {
          return text ? render('', { ...col, type: 'date', value: record[col.name] }, {
            value: text,
            data: record,
            name: col.name,
            format: col.format || col.inputFormat
          }) : <span className='text-muted'>-</span>
        }
        if (col.type.includes('switch')) {
          return text == col.trueValue ? col.onText : col.offText
        }
        if (col.type.includes('tpl') || col.type.includes('html')) {
          return render('', { ...col, type: 'tpl' }, { data: record })
        }
        if (['input-number', 'number'].includes(col.type)) {
          return render('', { ...col, type: 'number' }, { data: record, value: record[col.name] })
        }
        if (col.type.includes('input') || col.type.includes('static')) {
          return text ?? <span className='text-muted'>-</span >
        }
        return text
      }
    }
  }

  //批量插入  多条数据  key 列主键
  const insertMany = async (tableName: string, dataList: obj[], key: string) => {
    const res = await Shell.execInsert(tableName, dataList, key);
    return Promise.resolve(res.success);
  }

  //更新表中某条数据
  const update = async (tableName: string, newData: obj, key: string): Promise<boolean> => {
    const res = await Shell.execUpdate(tableName, [newData], key);
    return Promise.resolve(res.success);
  }

  //删除表中的某条数据
  const deleteByKey = async (tableName: string, keyValue?: string, key?: string): Promise<boolean> => {
    const res = await Shell.execDelete(tableName, keyValue, key);
    return Promise.resolve(res.success);
  }

  //查找表中的某条数据
  const findByKey = async (tableName: string, keyValue: any, key: string): Promise<obj> => {
    let res = await Shell.execFind(tableName, keyValue, key)
    if (res.success) {
      let result = res?.data?.content ? JSON.parse(res.data.content) : []
      let data = result?.length > 0
        ? typeof result[0] === 'string'
          ? JSON.parse(result[0])
          : result[0]
        : null
      return Promise.resolve(data)
    } else {
      console.error('查找出错', res)
      return Promise.reject();
    }
  }
  //判断是否已经下载过数据
  const hasDownload = async (): Promise<boolean> => {
    return new Promise(async (resolve, reject) => {
      var data = await findAll(name);
      if (data?.length > 0) {
        resolve(true)
      } else {
        resolve(false)
      }
    })
  }

  const handleDownload = async () => {
    const res = await hasDownload();
    if (res) {
      Modal.confirm({
        content: '已有下载数据，是否重新下载？',
        okText: __('Offline.reload'),
        cancelText: __('Offline.continue'),
        onOk: async () => {
          await clear(name);
          setOfflineTemplist([])
          download();
        }
      })
    } else {
      download()
    }
  }
  //删除
  const handleDelete = () => {
    Modal.confirm({
      content: '是否确认删除本条数据？',
      okText: '确定',
      cancelText: '取消',
      onOk: async () => {
        const value = currentRow?.[primaryField];
        const res = await deleteByKey(name, value, primaryField);
        if (res) {
          if (offlineTemplist.includes(value)) {
            const restTmp = offlineTemplist.filter(k => k !== value);
            setOfflineTemplist(restTmp);
          }
          const deleteIndex = offlineData.findIndex(item => item[primaryField] === value);
          if (deleteIndex != -1) {
            const newData = [...offlineData];
            newData.splice(deleteIndex, 1);
            setOfflineData(newData)
            setCurrentRow(null)
            message.success('删除成功！')
          }
        }
      }
    })
  }
  //重置
  const resetOfflineData = async () => {
    Modal.confirm({
      content: '是否确认重置数据？',
      okText: '确定',
      cancelText: '取消',
      onOk: async () => {
        setOfflineLoading(true)
        const res = await Shell.execDelete(name);
        if (!res.success) {
          setOfflineLoading(false)
          return message.warn('操作失败！')
        }
        const insertRes = await insertMany(name, [...originOfflineData.current], primaryField)
        if (!insertRes) {
          setOfflineLoading(false)
          return message.warn('操作失败！')
        }
        setOfflineLoading(false)
        setOfflineTemplist([])
        setOfflineData([...originOfflineData.current])
        setOfflineProgress(0)
        setCurrentRow(null)
        message.success('已重置数据')
      }
    })
  }
  //清空
  const clearOfflineData = async () => {
    Modal.confirm({
      content: '是否确认清空数据？',
      okText: '确定',
      cancelText: '取消',
      onOk: async () => {
        setOfflineLoading(true)
        await clear(name);
        setOfflineLoading(false)
        setOfflineTemplist([])
        setOfflineProgress(0)
        setOfflineData([])
        setCurrentRow(null)
        message.success('已清空数据')
      }
    })
  }
  //获取数据，渲染离线表格
  const offlineOpt = async () => {
    const shellData = await findAll(name);
    setOfflineData(shellData || [])
    originOfflineData.current = shellData || []
    const cols = offlineSchema.columns.map(item => columnExchange(item))
    setOfflineFormShow(true)
    setOfflineColumns(cols)
    fixOfflineTmpList()
  }
  //临时数据改变时，将临时数据置顶
  const fixOfflineTmpList = () => {
    if (offlineTemplist.length) {
      const restData = offlineData.filter(item => !offlineTemplist.includes(item[primaryField]));
      const tempDataList: any[] = offlineTemplist.map(k => offlineData.find(item => item[primaryField] == k)).filter(item => item !== undefined);
      setOfflineData([...tempDataList, ...restData])
    }
  }
  //提交数据
  const commitFormData = async (updateData: obj) => {
    const result = await update(name, updateData, primaryField);
    if (!result) return message.error('数据更新失败！')
    const data: obj = await findByKey(name, updateData?.[primaryField], primaryField);
    const primaryValue = data?.[primaryField]
    if (!offlineTemplist.includes(primaryValue)) {
      setOfflineTemplist([...offlineTemplist, primaryValue])
    }
    if (data) {
      const newData = offlineData.map((item: obj) => {
        if (item?.[primaryField] === data?.[primaryField]) {
          return data
        }
        return item
      })
      setOfflineData(newData)
      fixOfflineTmpList()
    }
  }

  //扫码查询
  const handleScanCode = async () => {
    return Shell.getScanCode(0, {
      input: true
    }).then((e) => {
      if (e.success === false) {
        return Promise.reject('');
      } else {
        let res = e.data.content;
        res && message.success('扫描成功')
        return scanCode(res);
      }
    });
  }
  const scanCode = async (code: string) => {
    if (!code) {
      message.error('该码无效！')
    } else {
      setOfflineLoading(true)
      const data = await findByKey(name, code, primaryField)
      if (data) {
        const primaryValue = data?.[primaryField]
        const tmpArr = JSON.parse(localStorage.getItem('offlineTemplist') ?? '')
        if (!tmpArr.includes(primaryValue)) {
          setOfflineTemplist([...tmpArr, primaryValue])
        }
        setCurrentRow(data)
        setOfflineFormShow(true)
        setOffline(false)
        setCodeVisible(false)
      } else {
        message.warning('无对应数据，请重新扫码！')
      }
      setOfflineLoading(false)
    }
  }
  //上传数据
  const handleUpload = async (uploadAction: ActionSchema) => {
    if (!offlineTemplist.length) {
      message.warning('当前数据暂未修改或进行扫描，无需上传！')
      return;
    }
    Modal.confirm({
      content: '是否确认上传离线操作数据？',
      okText: '上传',
      okType: 'danger',
      cancelText: '取消',
      onOk: async () => {
        const baseURL = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi || 'https://sasdev.sanfu.com/saas_dev';
        setOfflineLoading(true)
        setOfflineStatus(true)
        handleOfflineProgress()
        let uploadResult = await Shell.offlineUloadImg(name, baseURL + '/api/v1/upload/offline/picture', 'post');
        if (uploadResult.success === false) {
          message.error('图片上传失败！')
          setOfflineLoading(false)
          setOfflineStatus(false)
          throw new Error('图片上传失败！')
        }
        try {
          const allData = await findAll(name);
          const uploadData = offlineTemplist.map(item => allData.find((row: obj) => row[primaryField] === item))
          let zipData = Gzip(JSON.stringify(uploadData));
          const tmpList = [...offlineTemplist];
          env.fetcher({ url: (uploadAction as any).api.url, method: (uploadAction as any).api.method },
            { data: zipData }, { silent: true }).then(res => {
              if (res.status === 0) {
                clearInterval(offlineInterval.current)
                clearTimeout(offlineTimeout.current)
                offlineTimeout.current = null;
                setOfflineProgress(100);
                message.success(`本次上传成功${offlineTemplist.length}包`);
                const restData = allData.filter((item: any) => !offlineTemplist.includes(item[primaryField]))
                setOfflineLoading(false)
                setOfflineStatus(false)
                setOfflineProgress(0)
                setOfflineTemplist([])
                setCurrentRow(null)
                setOfflineData(restData)
                originOfflineData.current = restData;
                for (const iterator of tmpList) {
                  deleteByKey(name, iterator, primaryField)
                }
                search();
              } else {
                message.error(res.msg || '数据上传失败!')
                setOfflineLoading(false)
                setOfflineStatus(false)
              }
            })
        } catch (err) {
          message.error('提交数据出错！')
          setOfflineLoading(false)
          setOfflineStatus(false)
          throw new Error(err)
        }
      }
    })
  }

  //离线上传本地图片
  const addOfflineImage = (list: string[], fieldName: string) => {
    const oldData = currentRow?.[fieldName]
    let valueList: string[] = []
    const info = list.map(item => {
      const name = item.replace('localfile:///', '');
      valueList.push(item)
      return {
        addr: item,
        name,
        fileName: name
      }
    })
    if (oldData.value) {
      const newValue = [oldData.value, ...valueList].join(',')
      const newInfo = [...oldData.info, ...info]
      setCurrentRow({
        ...currentRow,
        [fieldName]: {
          value: newValue,
          info: newInfo
        }
      })
      commitFormData({
        ...currentRow,
        [fieldName]: {
          value: newValue,
          info: newInfo
        }
      })
    } else {
      setCurrentRow({
        ...currentRow,
        [fieldName]: {
          value: valueList.join(','),
          info
        }
      })
      commitFormData({
        ...currentRow,
        [fieldName]: {
          value: valueList.join(','),
          info
        }
      })
    }
  }

  //离线删除本地图片
  const delOfflineImage = (fieldName: string, fileIndex: number) => {
    const oldData = currentRow?.[fieldName];
    let valueList = oldData.value.split(',')
    let info = [...oldData.info]
    valueList.splice(fileIndex, 1)
    info.splice(fileIndex, 1)
    setCurrentRow({
      ...currentRow,
      [fieldName]: {
        value: valueList.join(','),
        info
      }
    })
    commitFormData({
      ...currentRow,
      [fieldName]: {
        value: valueList.join(','),
        info
      }
    })
  }
  //退出离线页面
  const offlineClose = async () => {
    const res = await hasDownload()
    const { offlinePageType } = offlineSchema;
    if (offlineStatus) {
      return message.warning('请在数据上传下载完成后再操作！')
    }
    if (res) {
      Modal.confirm({
        content: '当前离线数据未上传，是否确认退出离线模式？',
        okText: '确定',
        cancelText: '取消',
        onOk: () => {
          if (offlinePageType === 'detail') {
            history.back()
          } else {
            setOffline(false)
            setOfflineColumns([])
            setOfflineData([])
            setOfflineFormShow(false)
            setCurrentRow(null)
          }
        }
      })
    } else {
      if (offlinePageType === 'detail') {
        history.back()
      } else {
        setOffline(false)
        setOfflineColumns([])
        setOfflineData([])
        setOfflineFormShow(false)
        setCurrentRow(null)
      }
    }
  }

  // 没有离线报文直接返回
  if (!offlineSchema) return null

  // 进度条
  const renderOfflineLoading = () => {
    if (!offlineLoading) return null
    return <>
      <div className='offline-progress-mask'>
      </div>
      <div className='offline-progress-spinner'>
        {offlineStatus ?
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
            <div style={{ fontSize: 14, background: '#fcfcfa' }}>正在下载数据，请稍等...</div>
            <Progress status={'active'} style={{ width: 300, height: 18 }} percent={offlineProgress} size="default" />
          </div>
          : <Spin size='large' indicator={<LoadingOutlined style={{ fontSize: 32 }} spin />} spinning={offlineLoading} />
        }
      </div>
    </>
  }


  // 离线表格底部
  const renderOfflineFormFooter = () => {
    const { actions, actionLabel } = offlineSchema;
    const uploadAction = actions.find(item => item.actionType === 'offline-upload');
    return <div>
      {!!uploadAction && <Button size='small' type='primary' disabled={offlineTemplist.length == 0} onClick={() => handleUpload(uploadAction)}>{uploadAction.label}</Button>}
      <Button size='small' style={{ marginLeft: 12 }} type='primary' onClick={handleDownload}>下载</Button>
      <Button size='small' disabled={!(offlineData?.length > 0)} style={{ marginLeft: 12 }} onClick={() => {
        setOffline(true)
        offlineForm.current?.closest('.ant-drawer-body')?.scrollTo({ top: 0 })
      }} type='primary'>{actionLabel?.dataLabel || '本次下载信息'}</Button>
    </div>
  }

  // 离线表格体
  const renderOfflineFormShowDrawer = () => {
    if (!offlineFormShow) return null;
    return (<Drawer
      visible={offlineFormShow}
      width="100%"
      className="offline-drawer"
      closeIcon={<Icon icon='title-left' className="icon" style={{ width: '16px', height: '16px' }} />}
      onClose={offlineClose}
      destroyOnClose
      mask={false}
      getContainer={env.getModalContainer}
      zIndex={11}
      title={menuName || aliasTitle || '离线'}
      footer={renderOfflineFormFooter()}
    >
      <div
        className='offline-form-container'
        style={{ position: 'relative' }}
        key={currentRow?.[primaryField]}
        ref={offlineForm}
      >
        <div className='offline-scan-num'>
          <div onClick={() => {
            setOffline(true)
            offlineForm.current?.closest('.ant-drawer-body')?.scrollTo({ top: 0 })
          }}>扫描项：{offlineTemplist?.length ?? 0}</div>
        </div>
        {
          render('', {
            name: "offlineForm",
            title: "",
            type: "form",
            wrapWithPanel: false,
            onChange: (values: any, fields: { [key: string]: any }, formPristine: any) => {
              if (currentRow?.[primaryField]) {
                setCurrentRow({ ...currentRow, ...fields })
                commitFormData({ ...currentRow, ...fields })
              } else {
                message.warning('请先扫码！')
              }
            },
            data: currentRow,
            body: offlineSchema.columns.map(item => {
              if (item.type === 'lion-upload') {
                return {
                  ...item,
                  env: env,
                  type: 'offline-image',
                  formItem: true,
                  offlineData: currentRow?.[item.name],
                  offline: {
                    tableName: name,
                    primaryKey: primaryField,
                    primaryValue: currentRow?.[primaryField],
                    fieldName: item.name
                  },
                  offlineChange: addOfflineImage,
                  offlineDelete: delOfflineImage
                }
              } else {
                return {
                  ...item,
                  type: item.type || 'static',
                  value: currentRow?.[item.name],
                  format: item.format || item.inputFormat
                }
              }
            })
          })
        }
        <div style={{ marginTop: 8, padding: 16, background: '#fff' }}>
          <Button disabled={!currentRow} style={{ borderRadius: 8 }} onClick={handleDelete} danger type='primary' size='large' block >删除</Button>
        </div>
        {
          codeVisible &&
          <Modal className="scan-code-modal" afterClose={() => {
            setCodeValue('')
          }} visible={codeVisible} closable={false}
            okText="确定" cancelText="取消" width={320} style={{ top: 200 }}
            maskClosable={false}
            onCancel={() => {
              setCodeValue('')
              setCodeVisible(false)
            }}
            zIndex={1011}
            onOk={() => {
              if (codeValue) {
                scanCode(codeValue)
              } else {
                message.warn('请输入条码内容!')
              }
            }}
            getContainer={env.getModalContainer}
          >
            <div className="code-input-container">
              <div className="title">请输入条码内容</div>
              <div className="input-box">
                <Input onChange={(e) => {
                  setCodeValue(e.target.value)
                }} autoFocus
                  value={codeValue} />
              </div>
            </div>
          </Modal>
        }
        <div
          onTouchStart={(e) => {
            e.persist()
            e.preventDefault()
            e.stopPropagation()
            if (e.touches.length > 0) {
              const touch = e.touches[0];
              positionX.current = touch.clientX; // 记录触摸开始的横坐标
              positionY.current = touch.clientY; // 记录触摸开始的纵坐标
            }
          }}
          // onTouchMove={(e) => {
          //   e.preventDefault()
          // }}
          onTouchEnd={(e) => {
            e.persist()
            // e.preventDefault()
            // e.stopPropagation()
            if (e.changedTouches.length > 0) {
              const touch = e.changedTouches[0];
              const endX = touch.clientX; // 触摸结束的横坐标
              const endY = touch.clientY; // 触摸结束的纵坐标
              const moveX = endX - positionX.current; // 横向移动距离
              const moveY = endY - positionY.current; // 纵向移动距离
              if (moveX == 0 && moveY == 0) {
                // this.handleScanCode()
              } else {
                setPosition({
                  x: position.x + moveX,
                  y: position.y + moveY
                })
              }
            }
          }}
        >
          <Button
            onClick={handleScanCode}
            type="primary" size="large" shape="round"
            style={{ position: 'fixed', height: '46px', width: '196px', zIndex: '11', left: position.x + 'px', top: position.y + 'px' }}
            icon={<ScanOutlined />}>{offlineSchema?.actionLabel?.codeLabel || '点击扫码'}</Button>
          <Button
            type="link"
            size="large"
            style={{ position: 'fixed', backgroundColor: 'rgba(0,0,0,0.26)', color: 'white', paddingLeft: 30, left: position.x + 172 + 'px', top: position.y + 'px', borderColor: 'transparent', width: 104, height: 46, borderTopRightRadius: 40, borderBottomRightRadius: 40 }}
            onClick={(e) => {
              e.stopPropagation();
              setCodeVisible(true);
            }}
          >输入</Button>
        </div>
      </div>
    </Drawer>
    );
  }

  //离线状态时的按钮
  const renderOfflineUpload = () => {
    const uploadAction = offlineSchema.actions.find(item => item.actionType === 'offline-upload')
    return <div>
      <Button size='small' type='primary' onClick={handleScanCode}>{offlineSchema?.actionLabel?.codeLabel || '扫码'}</Button>
      {!!uploadAction && <Button size='small' style={{ marginLeft: 12 }} disabled={offlineTemplist.length < 1} type='primary' onClick={() => handleUpload(uploadAction)}>{uploadAction.label}</Button>}
      <Button size='small' style={{ marginLeft: 12, background: '#ffa200', color: '#fff' }} onClick={resetOfflineData}>重置</Button>
      <Button size='small' style={{ marginLeft: 12 }} danger type='primary' onClick={clearOfflineData}>清空</Button>
    </div>
  }
  const renderOfflineTableDrawer = () => {
    if(!offline) return null;
    return <Drawer
      visible={offline}
      width="100%"
      className="offline-drawer"
      closeIcon={<Icon icon='title-left' className="icon" style={{ width: '16px', height: '16px' }} />}
      onClose={() => setOffline(false)}
      title={menuName || aliasTitle || '离线'}
      mask={false}
      getContainer={env.getModalContainer}
      footer={renderOfflineUpload()}
    >
      <div className='offline-table-container' style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
        <div className='offline-scan-num'>
          <div>扫描项：{offlineTemplist?.length ?? 0}</div>
        </div>
        <div style={{ height: document.body.clientHeight - 38 - 45 - 64, overflow: 'hidden' }}>
          <VirtualTable tempList={offlineTemplist} bordered rowKey={primaryField} columns={offlineColumns} dataSource={offlineData} scroll={{ y: document.body.clientHeight - 38 - 38 - 45 - 64, x: '100vw' }} />
        </div>
      </div>
    </Drawer>
  }



  return (
    <>
      {renderOfflineLoading()}
      {renderOfflineFormShowDrawer()}
      {renderOfflineTableDrawer()}
    </>
  );
};

export default OfflineComponent;