import React from 'react';
import MSG from '../../../../utils/msgsub'
import { WrapperModal } from './style';
import Select from 'antd/lib/Select';
import Card from 'antd/lib/card';
import Button from 'antd/lib/button';
import Input from 'antd/lib/input';
import { Shell } from '../../../../../../utils/shell';
import SparkMD5 from 'spark-md5';
import { RendererEnv } from '../../../../../../env';
import './MainExport.css';
import Tag from 'antd/lib/tag';
import ArrowUpOutlined from '@ant-design/icons/lib/icons/ArrowUpOutlined';
import { createObject } from '../../../../../../utils/helper';
import { Icon } from '../../../../../../components/icons';
import { CheckCircleOutlined, ClockCircleOutlined } from '@ant-design/icons';
import { Api } from '../../../../../../types';
import { exportXLSXFromCross } from '../../../../../../utils/xlsx';

type OptionField = { label: string, name: string }

interface ExportTemplate {
  tempKey: string
  tempName: string
  exportFields: string
}

interface TaskData {
  TASK_ID: string
  DOWN_TASK_NAME: string
  DOWNLOAD_TIME: string | null
  DOWN_TASK_STATUS: string
  DOWNLOAD_CENTER: {
    value: string,
    info: { addr: string, name: string }[]
  }
}

interface ExportExcelProps {
  normalSelectAll?: boolean
  env: RendererEnv
  action: any
  ctx: any
  handleCancel: () => void
  data: any
}
interface ExportExcelState {
  visible: boolean
  loading: boolean
  fileType: string
  exportRange: string
  exportType: string
  tempId: string
  tempName: string
  exportFields: string[]
  exportTemplates: ExportTemplate[]
  taskDatas: TaskData[]
  taskTotal: number
  keepDataFormat: string
}

export default class LionExportExcel extends React.Component<ExportExcelProps, ExportExcelState> {

  static readonly DEFAULT_TEMP_ID = 'defaultTempId'
  static readonly DEFAULT_TEMP_NAME = '默认模板'

  _fileTypeList: OptionField[] = [{ label: '数据文件', name: 'dataFile' }]
  _exportRangeList: OptionField[] = [{ label: '选中数据', name: '0' }, { label: '所有数据', name: '1' }]
  _exportTypeList: OptionField[] = [{ label: '按设置列导出', name: 'column' }, { label: '按模板导出', name: 'template' }]
  _exportDataFormat: OptionField[] = [{ label: '导出为原始数据', name: '0' }, { label: '保留数据格式', name: '1' }]
  allExportColumns: OptionField[]
  defaultTemplate: ExportTemplate
  appId = sessionStorage.getItem('appId') ?? ''

  constructor(props: ExportExcelProps) {
    super(props)
    const exportColumns = props.ctx.exportFields as OptionField[]
    const isSelected = props.ctx.selectedItems.length > 0
    this.handleWsEvent = this.handleWsEvent.bind(this)
    this.allExportColumns = exportColumns
    this.defaultTemplate = { tempKey: LionExportExcel.DEFAULT_TEMP_ID, tempName: LionExportExcel.DEFAULT_TEMP_NAME, exportFields: exportColumns.map(field => field.name).join(',') }
    this.state = {
      visible: true,
      loading: false,
      fileType: 'dataFile',
      exportRange: isSelected ? '0' : '1',
      exportType: 'column',
      tempId: LionExportExcel.DEFAULT_TEMP_ID,
      tempName: LionExportExcel.DEFAULT_TEMP_NAME,
      exportFields: exportColumns.map(field => field.name),
      exportTemplates: [this.defaultTemplate],
      taskDatas: [],
      taskTotal: 0,
      keepDataFormat: '1'
    }
  }

  componentDidMount() {
    this.handleGetTemplate()
    this.handleGetTask()

    window.addEventListener('receiveWsMsgData', this.handleWsEvent)
  }

  componentWillUnmount() {
    window.removeEventListener('receiveWsMsgData', this.handleWsEvent)
  }

  handleWsEvent(e: CustomEvent) {
    const data = e.detail
    if (data.jobName === 'downloadJob') {
      this.handleGetTask()
    }
  }

  async handleGetTask() {
    const { env, data } = this.props
    const taskApi: Api = { method: 'get', url: `/api/v1/download/data?APP_ID=${this.appId}&page_id=${data.pageId}` }
    const res = await env.fetcher(taskApi)
    if (res.status === 0 && res.data != null && Array.isArray(res.data.items)) {
      this.setState({ taskDatas: res.data.items.slice(0, 5), taskTotal: res.data.total })
    }
  }

  async handleDeleteTask(id: string) {
    const { env } = this.props
    const taskDeleteApi: Api = { method: 'get', url: `/api/v1/download/batch/del?SELECTION_IDS=${id}` }
    const res = await env.fetcher(taskDeleteApi)
    if (res.status === 0) {
      MSG._success(res.msg)
      this.handleGetTask()
    }
  }

  async handleGetTemplate() {
    const { env, ctx } = this.props
    const selectApi = ctx.selectApi
    if (selectApi) {
      const res = await env.fetcher(selectApi)
      if (res.status === 0) {
        const template = res.data as ExportTemplate[]
        template.push(this.defaultTemplate)
        this.setState({
          exportTemplates: template,
          tempId: template[0].tempKey,
          tempName: template[0].tempName,
          exportFields: template[0].exportFields.split(',')
        })
      }
    }
  }

  async handleSaveTemplate() {
    const { env, ctx } = this.props
    const setApi = ctx.setApi
    if (setApi) {
      const { tempName, exportFields } = this.state
      const tempKey = SparkMD5.hash(tempName)
      const res = await env.fetcher(setApi, { tempKey, tempName, exportFields: exportFields.join(',') })
      if (res.status === 0) {
        this.handleGetTemplate()
      } else {
        MSG._error(res.msg, env?.getModalContainer)
      }
    }
  }

  async handleDeleteTemplate() {
    const { env, ctx } = this.props
    const deleteApi = ctx.deleteApi
    if (deleteApi) {
      const { tempId } = this.state
      const res = await env.fetcher(deleteApi, { tempKey: tempId })
      if (res.status === 0) {
        this.handleGetTemplate()
      } else {
        MSG._error(res.msg, env?.getModalContainer)
      }
    }
  }

  handleChangeTemplate(tempId: string) {
    const fields = this.state.exportTemplates.find(item => item.tempKey === tempId)
    this.setState({ tempId, tempName: fields?.tempName ?? '', exportFields: fields?.exportFields.split(',') ?? [] })
  }

  handeCancel = () => {
    this.props.handleCancel()
    this.setState({ visible: !this.state.visible })
  }

  openDownloadDialog = (url: any, saveName: string) => {
    return new Promise((resolve, reject) => {
      resolve('')
    }).then(res => {
      if (typeof url == 'object' && url instanceof Blob) {
        url = URL.createObjectURL(url); // 创建blob地址
      }
      var aLink = document.createElement('a');
      aLink.href = url;
      aLink.download = saveName || ''; // HTML5新增的属性，指定保存文件名，可以不要后缀，注意，file:///模式下不会生效
      var event;
      if (window.MouseEvent) event = new MouseEvent('click');
      else {
        event = document.createEvent('MouseEvents');
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      }
      aLink.dispatchEvent(event);
    })
  }

  handleSubmit = async () => {
    const { exportRange, exportFields, exportType, keepDataFormat } = this.state;
    const { ctx, env, data, action } = this.props;
    const { selectedItems, exportSetColumnFields } = ctx;
    if (exportRange === '0' && selectedItems?.length <= 0) {
      MSG._error('选中项为空', env?.getModalContainer)
      return
    }
    if(action.name === 'default_export' && exportRange === '0') {
      ctx?.handleExportDefault?.(keepDataFormat === '1', exportType, exportType === 'template' ? exportFields : undefined)
      return;
    }
    const baseUrl = env?.axiosInstance?.defaults?.baseURL;
    const fields = exportType === 'template' ? exportFields.join(',') : exportSetColumnFields.join(',')
    this.setState({ loading: true })
    const obj = createObject(data, { ...ctx, exportType: Number(exportRange), exportFields: fields, keepDataFormat: keepDataFormat === '1' })
    if (!Shell.hasShell()) {
      env.fetcher(ctx.api, obj).then((res: any) => {
        if (res?.status === 0) {
          res?.data && this.openDownloadDialog((baseUrl ?? res?.reqUrl) + res?.data?.fileUrl, res?.data?.fileName)
          MSG._success(res?.msg, env?.getModalContainer);
          this.setState({ visible: false })
        } else if (res?.status === 301) {
          this.handleGetTask()
          MSG._info(res?.msg, env?.getModalContainer);
        } else {
          MSG._error(res?.msg, env?.getModalContainer);
        }
      }).catch((err: any) => {
        MSG._error('导出出错', env?.getModalContainer)
      }).finally(() => this.setState({ loading: false }))
    } else {
      env.fetcher(ctx.api, obj).
        then(async (res: any) => {
          if (res?.status === 301) {
            MSG._info(res?.msg);
            this.handleGetTask()
            return
          }
          this.setState({ visible: false })
          const confirmd = await env.confirm('是否要保存并打开文件?');
          if (confirmd) {
            const shellRes = await Shell.download((baseUrl ?? res?.reqUrl) + res?.data?.fileUrl, res?.data?.fileName, 1);
            if (shellRes?.success) {
              MSG._success(shellRes?.msg!, env?.getModalContainer);
            } else {
              MSG._error(shellRes?.msg!, env?.getModalContainer);
            }
          } else {
            MSG._info('用户取消', env?.getModalContainer)
          }
        }).catch((err: any) => {
          MSG._error('导出出错', env?.getModalContainer)
        }).finally(() => this.setState({ loading: false }))
    }
  }

  handleReset = () => {
    const { exportTemplates } = this.state
    const isSelected = this.props.ctx.selectedItems.length > 0
    this.setState({
      fileType: 'dataFile',
      exportRange: isSelected ? '0' : '1',
      exportType: 'column',
      tempId: exportTemplates.length > 0 ? exportTemplates[0].tempKey : '',
      tempName: exportTemplates.length > 0 ? exportTemplates[0].tempName : '',
      exportFields: exportTemplates.length > 0 ? exportTemplates[0].exportFields.split(',') : []
    })
  }

  renderSelectTag = (props: any) => {
    const { label, value, closable, onClose } = props;
    const onPreventMouseDown = (event: React.MouseEvent<HTMLSpanElement>) => {
      event.preventDefault();
      event.stopPropagation();
    };
    return (
      <Tag
        icon={<ArrowUpOutlined onClick={() => this.handleSort(value)} />}
        onMouseDown={onPreventMouseDown}
        closable={closable}
        onClose={onClose}
        style={{ margin: 3 }}
      >
        {label}
      </Tag>
    );
  }

  handleSort(name: string) {
    const { exportFields } = this.state
    const tempArr = Array.from(exportFields)
    const index = tempArr.findIndex(item => name === item)
    if (index > 0) {
      const a = tempArr[index - 1]
      const b = tempArr[index]
      tempArr[index - 1] = b
      tempArr[index] = a
      this.setState({ exportFields: tempArr })
    }
  }

  render() {
    const { env, normalSelectAll } = this.props;
    const { visible, loading, fileType, exportRange, exportType, tempId, tempName, exportFields, exportTemplates,
      taskDatas, keepDataFormat } = this.state
    const baseUrl = env?.axiosInstance?.defaults?.baseURL ?? ''

    return (
      <div className="lion-export-wrapper">
        <WrapperModal
          wrapClassName='fastlion-export ant-modal-adaptation-style'
          visible={visible}
          closable
          getContainer={env?.getModalContainer as any}
          onCancel={this.handeCancel}
          title="文件导出"
          zIndex={9999}
          maskStyle={{ zIndex: 9999 }}
          footer={
            <div className="lion-export-btns"
              style={{
                display: 'flex',
                width: '100%',
                justifyContent: 'space-between',
                overflow: 'hidden'
              }}
            >
              <Button onClick={this.handleReset}>重置</Button>
              <div>
                <Button onClick={this.handeCancel}>取消</Button>
                <Button style={{ marginLeft: '10px' }} type='primary' loading={loading} onClick={this.handleSubmit.bind(this)}>确定</Button>
              </div>
            </div>
          }
        >
          <div className='export-content'>
            <div className='export-content-select'>
              <div className='export-content-type'>
                <span className='export-content-text' >文件类型</span>
                <Select dropdownClassName={`dropdown-select-style`} dropdownStyle={{ zIndex: 10019 }} bordered={false} placeholder='文件类型' value={fileType} onChange={type => this.setState({ fileType: type })}>
                  {this._fileTypeList.map((item, index) => <Select.Option key={index} value={item.name}>{item.label}</Select.Option>)}
                </Select>
              </div>
              <div className='export-content-range' >
                <span className='export-content-text' >导出范围</span>
                <Select dropdownClassName={`dropdown-select-style`} dropdownStyle={{ zIndex: 10019 }} bordered={false} placeholder='导出范围' disabled={normalSelectAll} value={exportRange} onChange={type => this.setState({ exportRange: type })}>
                  {this._exportRangeList.map((item, index) => <Select.Option className='lion-option-disabled' key={index} value={item.name} disabled={index !== parseInt(exportRange)} >{item.label}</Select.Option>)}
                </Select>
              </div>
              <div className='export-content-mode' >
                <span className='export-content-text'>导出方式</span>
                <Select dropdownClassName={`dropdown-select-style`} dropdownStyle={{ zIndex: 10019 }} bordered={false} placeholder='导出方式' value={exportType} onChange={type => this.setState({ exportType: type })}>
                  {this._exportTypeList.map((item, index) => <Select.Option key={index} value={item.name}>{item.label}</Select.Option>)}
                </Select>
              </div>
              <div className='export-content-mode' >
                <span className='export-content-text'>数据格式</span>
                <Select dropdownClassName={`dropdown-select-style`} dropdownStyle={{ zIndex: 10019 }} bordered={false} placeholder='导出方式' value={keepDataFormat} onChange={type => this.setState({ keepDataFormat: type })}>
                  {this._exportDataFormat.map((item, index) => <Select.Option key={index} value={item.name}>{item.label}</Select.Option>)}
                </Select>
              </div>
              <div className='export-content-template' style={{ display: exportType === 'template' ? 'block' : 'none' }}>
                <span className='export-content-text'>导出模板</span>
                <Select dropdownClassName={`dropdown-select-style`} className='my-select' dropdownStyle={{ zIndex: 10019 }} bordered={false} value={tempId} onChange={id => this.handleChangeTemplate(id)}>
                  {exportTemplates.map(temp => <Select.Option key={temp.tempKey} value={temp.tempKey}>{temp.tempName}</Select.Option>)}
                </Select>
                {/* <Button style={{ marginLeft: '10px', fontSize: '13px' }} onClick={() => this.setState({ showSetting: true })}>设置</Button> */}
              </div>
              {exportType === 'template' &&
                <div className='export-content-field'>
                  <Card className='export-content-field-card' size="small" title="导出字段" >
                    <div className='export-content-field-card-select'>
                      <Select dropdownClassName={`dropdown-select-style`} tagRender={this.renderSelectTag} value={exportFields} className='my-field-select' placeholder='请选择导出字段' mode="multiple" dropdownStyle={{ zIndex: 10019 }}
                        onChange={value => this.setState({ exportFields: value })}>
                        {this.allExportColumns.map((field) => <Select.Option key={field.name} value={field.name}>{field.label}</Select.Option>)}
                      </Select>
                    </div>
                    <div className='export-content-field-card-button' >
                      <Input addonBefore="模板名称" value={tempName} placeholder='请输入' onChange={e => this.setState({ tempName: e.target.value })} />
                      <Button style={{ fontSize: '13px', borderRadius: '0px' }} type='primary' onClick={() => this.handleSaveTemplate()}>保存</Button>
                      <Button style={{ fontSize: '13px', borderRadius: '0px 2px 2px 0px' }} disabled={tempId === LionExportExcel.DEFAULT_TEMP_ID} onClick={() => this.handleDeleteTemplate()}>删除</Button>
                    </div>
                  </Card>
                </div>
              }
            </div>
            <div className='export-content-show'>
              {taskDatas.map(data => {
                const { TASK_ID: id, DOWN_TASK_NAME: name, DOWNLOAD_CENTER: file, DOWNLOAD_TIME: time, DOWN_TASK_STATUS: status } = data
                return (
                  <div className='export-content-show-export' key={id}>
                    <div className='export-content-show-icon' style={{ visibility: time == null && status == '2' ? 'visible' : 'hidden' }} />
                    {status == '1' ? <ClockCircleOutlined style={{ marginLeft: 8, color: '#FDA71E' }} /> : <CheckCircleOutlined style={{ marginLeft: 8, color: 'green' }} />}
                    <span className='ellipsis' title={name} style={{ marginLeft: 8, width: 270 }} >{name}</span>
                    <Button color='gray' onClick={() => {
                      const addr = file.info[0].addr ?? ''
                      const url = baseUrl + (addr.includes('?') ? `${addr}&taskId=${id}` : `${addr}?taskId=${id}`)
                      this.openDownloadDialog(url, file.info[0].name)
                    }} style={{ fontSize: 14, visibility: status == '2' ? 'visible' : 'hidden' }} size='small' type='link'><Icon icon={'#icon-tooltool_download'} className="icon" symbol /></Button>
                    <Button color='gray' onClick={() => this.handleDeleteTask(id)} style={{ fontSize: 14, visibility: status == '2' ? 'visible' : 'hidden' }} size='small' type='link'><Icon icon={'#icon-tooltool_delete'} className="icon" symbol /></Button>
                  </div>
                )
              })}
              {this.state.taskTotal > 5 && <div style={{ color: 'gray' }}>...</div>}
              {this.state.taskTotal > 5 && <div style={{ color: 'gray' }}>此处仅展示最近5条下载任务</div>}
              <Button onClick={() => { this.setState({ visible: false }); env.onPageLink?.('export', 'export', '', 'redirectApp=document', undefined) }} style={{ padding: '6px 0' }} size='small' type='link'>更多下载任务</Button>
            </div>
          </div>
        </WrapperModal>
      </div >
    )
  }
}
