import React from "react";
import Form from 'antd/lib/form';
import InputNumber from 'antd/lib/input-number';
import Select from 'antd/lib/select';
import Radio from 'antd/lib/Radio';
import { Spinner } from "../../../../components";
import Button from '../../../../components/Button'
import { CloseIcon } from "../../../../components/icons";
import { Api } from '../../../../types';
import message from 'antd/lib/message';
import { RendererEnv } from '../../../../env';
import { FormInstance } from "antd/es/form";
import { Template, LabelData, PrinterParam, pageOptions, sizeOptions } from '../types';
import { buildLabelTemplate, setLabelTemplateData } from "../../../../utils/print/util";
import { billPrint } from "../../../../utils/print";
import moment from "moment";
import Row from "antd/lib/row";
import Col from "antd/lib/col";

const { Option } = Select;

interface BillPrintProps {
  printType: string
  labelDataApi: Api; // 获取标签数据数组
  templateApi: Api; // 获取标签模板
  callbackApi?: any; // 打印回调，发送打印时间
  labelId?: string;
  env: RendererEnv
  classnames: (...args: any[]) => string;
  ctx: {
    items: Array<any>; // 选中的行数据
    selectedItems: Array<any>; // 选中的行数据
    ids: string; // 多个 id 值用英文逗号隔开的字符串，前提是行数据中有 id 字段，或者有指定的 primaryField 字段
    primaryField?: string; // CRUD 设置 ID 字段名
    [key: string]: any; // 第一行的所有行数据也会包含进去
  };
  onHide: (e?: any) => void; // modal关闭回调
  isRow?: boolean; // 是否行内按钮
  query?: any;
  [key: string]: any;
  printers: string[]
  baseUrl: string
  modalContainer?: () => HTMLElement
  popupContainer?: () => HTMLElement
}

interface BillPrintState {
  previewLoading: boolean
  templates: Template[]
}

interface BillPrintFormValues {
  printer: string // 打印机名
  label: string // 标签模板名
  pageSize: string // 纸张类型
  pageWidth: number // 纸张宽度mm
  pageHeight: number // 纸张高度mm
  /** 纵向/横向 */
  direction: 0 | 1
  /** 打印份数  */
  count: number
}

export default class BillPrint extends React.Component<BillPrintProps, BillPrintState> {

  formRef = React.createRef<FormInstance<BillPrintFormValues>>()

  cacheLabelData?: LabelData

  constructor(props: BillPrintProps) {
    super(props)
    this.state = {
      previewLoading: false,
      templates: []
    }
  }

  async componentDidMount() {
    const templates = await this.getTemplates()
    this.setState({ templates }, () => {
      if (templates.length > 0) {
        this.formRef.current?.setFieldsValue({
          label: templates[0].tempName
        })
      }
    })
  }

  componentWillUnmount() {
    this.cacheLabelData = undefined
  }

  // 获取模板数据
  async getTemplates() {
    const { env, templateApi, data } = this.props
    const templates: Template[] = await env.fetcher(templateApi, data).then(res => {
      if (res.status === 0) {
        return res.data
      } else {
        return []
      }
    })
    return templates
  }

  async getLabelData() {
    if (this.cacheLabelData) {
      return this.cacheLabelData
    }
    const { env, ctx, labelDataApi, primaryField, isRow, printType, data: flowData } = this.props
    // printType: 0选中数据  1全量打印  2行内打印
    let data: any = {}
    if (printType == 'bill') {
      if (isRow) {
        data = ctx
        data.printType = 2
      } else {
        if (!ctx?.ids) {
          message.info('请先选择行数据')
          return
        }
        data.printType = 0
        data.ids = ctx.ids
        data.primaryField = primaryField
      }
    } else {
      data = flowData
    }
    const res = await env.fetcher(labelDataApi, data)
    if (res.status === 0) {
      const data = res.data as LabelData
      this.cacheLabelData = data
      return data
    } else {
      message.error(res.msg)
      return null
    }
  }

  async handleBillPreview() {
    this.setState({ previewLoading: true })
    const values = await this.formRef.current!.validateFields()
    const labelData = await this.getLabelData()

    const template = this.state.templates.find(temp => temp.tempName === values.label)
    if (labelData && template) {
      const { tempContent, tableColumn, width, height } = template
      const labelTemplate = buildLabelTemplate(tempContent)
      const templateDatas = setLabelTemplateData(labelTemplate, labelData.items, this.props.baseUrl, tableColumn)
      const param: PrinterParam = {
        ...values,
        pageWidth: width,
        pageHeight: height,
        preview: true,
        direction: values.direction === 0,
        arrange: false,
        marginTop: 0,
        marginLeft: 0,
        rowSpacing: 0,
        colSpacing: 0
      }
      billPrint({ ...param, templateDatas }, () => {
        this.setState({ previewLoading: false })
      })
    }
  }

  async handleBillPrint() {
    const values = await this.formRef.current!.validateFields()
    const labelPrintData = await this.getLabelData()
    const template = this.state.templates.find(temp => temp.tempName === values.label)
    if (labelPrintData && template) {
      const { tempContent, tableColumn, width, height } = template
      const labelTemplate = buildLabelTemplate(tempContent)
      const templateDatas = setLabelTemplateData(labelTemplate, labelPrintData.items, this.props.baseUrl, tableColumn)
      const param: PrinterParam = {
        ...values,
        pageWidth: width,
        pageHeight: height,
        preview: false,
        direction: values.direction === 0,
        arrange: false,
        marginTop: 0,
        marginLeft: 0,
        rowSpacing: 0,
        colSpacing: 0
      }
      billPrint({
        ...param,
        templateDatas
      }, () => {
        this.savePrintInfo()
      })
    }
  }

  savePrintInfo() {
    // 获取保存请求的地址
    const { env: { fetcher }, ctx, callbackApi } = this.props
    if (!callbackApi) return
    const PRINT_TIME = moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
    callbackApi.data = {
      callbackList: {
        ...callbackApi.data,
        PRINT_TIME
      }
    }
    fetcher(callbackApi, { ids: ctx?.ids })
  }

  render() {
    const { classnames: cx, translate: __, popupContainer, printers, onHide } = this.props
    const { previewLoading, templates } = this.state
    const templateNames = templates.map(item => item.tempName)

    return (
      <>
        <div className={cx('Modal-header')}>
          <div className={cx('Modal-title')}>
            {__('CRUD.formPrint')}
            <a
              data-tooltip={__('Dialog.close')}
              onClick={(e) => onHide(e)}
              className={cx('Modal-close')}
            >
              <CloseIcon />
            </a>
          </div>
        </div>
        <div className={cx('Modal-body')}>
          <div className='print-form-container'>
            <div className='preview-container'>
              <Spinner size="md" overlay show={previewLoading} />
              <iframe id='bill-preview' width='100%' height='100%'></iframe>
            </div>
            <Form style={{ width: 350, }} ref={this.formRef} colon={false} layout="vertical" >
              <div className="print-setting">
                <div className="print-setting-label">打印设备</div>
                <div className="print-setting-content">
                  <Row gutter={10}>
                    <Col span={12}>
                      <Form.Item name="printer" label={__('CRUD.printer')} initialValue={printers[0] || ''} rules={[{ required: true, message: `${__('CRUD.selectPrinter')}` }]}>
                        <Select
                          getPopupContainer={popupContainer}
                          dropdownClassName='label-print-selector' >
                          {printers.map(item => <Option key={item} value={item}>{item}</Option>)}
                        </Select>
                      </Form.Item>
                    </Col>
                    <Col span={12}>
                      <Form.Item name="pageSize" label={__('CRUD.pageSize')} initialValue={pageOptions[0].value} rules={[{ required: true, message: `${__('CRUD.selectPage')}` }]}>
                        <Select showSearch
                          getPopupContainer={popupContainer}
                          dropdownClassName='label-print-selector'
                          onChange={(value: any) => {
                            const [pageWidth, pageHeight] = sizeOptions[value as string]
                            this.formRef.current?.setFieldsValue({
                              pageWidth: pageWidth,
                              pageHeight: pageHeight
                            })
                          }}
                        >
                          {pageOptions?.map(item => <Option key={item.value} value={item.value}>{item.label}</Option>)}
                        </Select>
                      </Form.Item>
                    </Col>
                  </Row>
                  <Row gutter={10}>
                    <Col span={12}>
                      <Form.Item name="pageWidth" label={__('width')} initialValue={sizeOptions[pageOptions[0].value][0]} rules={[{
                        validator: async (rule, value) => {
                          if (value < 0 || value > 1000) {
                            throw new Error(`${__('CRUD.fillIn')}1-1000`);
                          }
                        }
                      }]} >
                        <InputNumber className='w-full' min={0} max={1000} />
                      </Form.Item>
                    </Col>
                    <Col span={12}>
                      <Form.Item name="pageHeight" label={__('height')} initialValue={sizeOptions[pageOptions[0].value][1]} rules={[{
                        validator: async (rule, value) => {
                          if (value < 0 || value > 1000) {
                            throw new Error(`${__('CRUD.fillIn')}1-1000`);
                          }
                        }
                      }]}>
                        <InputNumber className='w-full' min={0} max={1000} />
                      </Form.Item>
                    </Col>
                  </Row>
                </div>
                <div className="print-setting-label">纸张设置</div>
                <div className="print-setting-content">
                  <Row >
                    <Col span={12}>
                      <Form.Item name="direction" label={__('direction')}
                        initialValue={0}
                        rules={[{ required: true, }]}>
                        <Radio.Group>
                          <Radio value={0} style={{ marginRight: 32 }}>{__('vertical')}</Radio>
                          <Radio value={1}>{__('horizontal')}</Radio>
                        </Radio.Group>
                      </Form.Item>
                    </Col>
                  </Row>
                </div>
                <div className="print-setting-label">打印内容</div>
                <div className="print-setting-content">
                  <Row>
                    <Col span={24}>
                      <Form.Item name="label" label={__('CRUD.selectLabel')} rules={[{ required: true, message: `${__('CRUD.select_Label')}` }]}>
                        <Select getPopupContainer={popupContainer} dropdownClassName='label-print-selector'>
                          {templateNames?.map(item => <Option key={item} value={item} >{item}</Option>)}
                        </Select>
                      </Form.Item>
                    </Col>
                  </Row>
                  <Row>
                    <Col span={12}>
                      <Form.Item name="count" label={__('CRUD.copies')} initialValue={1} rules={[{
                        validator: async (rule, value) => {
                          if (value < 1 || value > 100) {
                            throw new Error(`${__('CRUD.fillIn')}1-100`);
                          }
                        }
                      }]}>
                        <InputNumber className='input-count' min={1} max={100} formatter={value => value ? Number(value).toFixed(0) : ''} />
                      </Form.Item>
                    </Col>
                  </Row>
                </div>
              </div>
            </Form>
          </div>
        </div>
        <div className={cx('Modal-footer')} >
          <Button level="primary" onClick={this.handleBillPreview.bind(this)} >{__('preview')}</Button>
          <Button level="primary" onClick={this.handleBillPrint.bind(this)} >{__('print')}</Button>
          <Button onClick={(e: any) => onHide(e)}>{__('cancel')}</Button>
        </div >
      </>
    )
  }

}