import React from 'react'
import Form from 'antd/lib/form';
import InputNumber from 'antd/lib/input-number';
import Select from 'antd/lib/select';
import Tabs from "antd/lib/tabs";
import Radio from "antd/lib/radio";
import Row from "antd/lib/row";
import Col from "antd/lib/col";
import Empty from "antd/lib/empty";
import Checkbox from "antd/lib/checkbox";
import Input from "antd/lib/input";
import message from 'antd/lib/message';
import { Spinner } from "../../../../components";
import Button from '../../../../components/Button'
import { CloseIcon } from "../../../../components/icons";
import { pageOptions, sizeOptions, SettingValues, DetailOptionValues, IFPTableValue } from '../types';
import { detailPrint } from '../../../../utils/print';
import { RendererEnv } from '../../../../env';
import { EventEnum, EventSub } from '../../../../utils/sub';
import { Api } from '../../../../types';
import { buildDetailTemplate } from '../../../../utils/print/util';
import { IColumn } from '../../../../store/table';
import { flatMap } from 'lodash';

const { Option } = Select;

interface IProps {
  superRole: boolean
  env: RendererEnv
  printers: string[]
  printInfo?: { title: string, subTitle: string, extraTitle: string, printFlow?: boolean }
  [key: string]: any;
}

interface ITableValue {
  name: string,
  isPrint: boolean,
  label: string,
  fontSize: number,
  fontFamily: string
  columns: Pick<IFPTableValue, 'name' | 'title' | 'printType' | 'align'>[]
}

interface IState extends DetailOptionValues {
  previewLoading: boolean
  saveLoading: boolean
  showEmpty: boolean
  isDynamicSubTitle: boolean
  dynamicSubTilteList: string[]
  // setting
  printer: string
  page: string
  width: number
  height: number
  top: number
  bottom: number
  left: number
  right: number
  direction: 'vertical' | 'horizontal'
  copies: number
  scale: number
  // table
  detailTableValues: ITableValue[]
}

const tableColumns = [
  {
    title: '标题',
    key: 'title',
    type: 'text',
    width: 70,
  },
  {
    title: '打印',
    key: 'printType',
    type: 'select',
    width: 40,
    options: [
      { label: '是', value: 'all' },
      { label: '否', value: 'none' },
    ]
  }
]


export default class DetailPrint extends React.Component<IProps, IState> {

  formName: string
  showDebugPreviewButton = Boolean(localStorage.getItem('SF_PREVIEW_BTN'))
  reportTitleSql?: string
  reportSubTitleSql?: string

  constructor(props: IProps) {
    super(props)
    this.formName = props.name
    const setting = localStorage.getItem('SF_PrintSetting') ?? '{}'
    const settingObj = JSON.parse(setting)
    this.state = {
      previewLoading: false,
      saveLoading: false,
      showEmpty: true,
      isDynamicSubTitle: false,
      dynamicSubTilteList: [],
      //
      printer: settingObj.printer ?? props.printers[0],
      page: settingObj.page ?? 'A4',
      width: settingObj.width ?? 210,
      height: settingObj.height ?? 297,
      top: settingObj.top ?? 10,
      bottom: settingObj.bottom ?? 10,
      left: settingObj.left ?? 10,
      right: settingObj.right ?? 10,
      direction: settingObj.direction ?? 'vertical',
      copies: settingObj.copies ?? 1,
      scale: settingObj.scale ?? 100,
      //
      showTitle: true,
      title: props.printInfo?.title ?? (props.dialogTitle ?? ''),
      showDynamicSubTitles: true,
      dynamicSubTiltes: [],
      showDate: true,
      showPageNum: true,
      showPrinter: true,
      showLogo: true,
      showBarCode: false,
      showQRCode: false,
      detailTableValues: []
    }
  }

  componentDidMount() {
    this.handleGetSetting()
    EventSub.emit(EventEnum.DomPrint, this.formName, ({ name, columns, label }: { name: string, label: string, columns: (IColumn & { hidden: boolean })[] }) => {
      const printType: 'all' | 'none' = 'all'
      this.setState(pre => ({
        detailTableValues: pre.detailTableValues.concat({
          name,
          label,
          isPrint: true,
          fontSize: 12,
          fontFamily: '宋体',
          columns: flatMap(columns ?? [], column => column?.hidden || column.name === 'operation' ? [] : { title: column.label, printType, name: column.name ?? '', align: column.align ?? 'left' })
        })
      }))
    })
  }

  componentWillUnmount() {
    const settingValues = {
      printer: this.state.printer,
      page: this.state.page,
      width: this.state.width,
      height: this.state.height,
      top: this.state.top,
      bottom: this.state.bottom,
      left: this.state.left,
      right: this.state.right,
      direction: this.state.direction,
      copies: this.state.copies,
      scale: this.state.scale,
    }
    localStorage.setItem('SF_PrintSetting', JSON.stringify(settingValues))
  }

  async handleGetSetting() {
    const payload = await this.props.env.fetcher(`/api/v1/form/print/${this.formName}/select`)
    const data = payload.data
    if (payload.ok && data != null) {
      this.reportTitleSql = data.reportTitleSql
      this.reportSubTitleSql = data.reportSubTitleSql
      const isDynamicTitle = data.isDynamicTitle ?? false
      const isDynamicSubTitle = data.isDynamicSubTitle ?? false

      this.setState(pre => {
        const defaultValues: ITableValue[] = data.detailTableValues
        let detailTableValue = pre.detailTableValues
        if (Array.isArray(defaultValues)) {
          detailTableValue = pre.detailTableValues.map(values => {
            const target = defaultValues.find(item => item.name == values.name)
            if (target) {
              return {
                ...target,
                columns: values.columns.map(column => {
                  const temp = target.columns.find(item => item.name == column.name)
                  return temp ? { ...column, printType: temp.printType } : column
                })
              }
            }
            return values
          })
        }
        return ({
          isDynamicSubTitle,
          dynamicSubTilteList: isDynamicSubTitle ? data.reportSubTitle ?? [] : [],
          showTitle: data.showTitle ?? pre.showTitle,
          title: isDynamicTitle ? data.reportTitle : data.title ?? pre.title,
          showDynamicSubTitles: data.showDynamicSubTitles ?? pre.showDynamicSubTitles,
          dynamicSubTiltes: data.reportSubTitle?.filter((val: string, index: number) => data.dynamicSubTiltes?.includes(index)) ?? pre.dynamicSubTiltes,
          showDate: data.showDate ?? pre.showDate,
          showPageNum: data.showPageNum ?? pre.showPageNum,
          showPrinter: data.showPrinter ?? pre.showPrinter,
          showLogo: data.showLogo ?? pre.showLogo,
          showBarCode: data.showBarCode ?? pre.showBarCode,
          showQRCode: data.showQRCode ?? pre.showQRCode,
          detailTableValues: detailTableValue
        })
      }, () => { this.handleDetailPrint(true, false) })
    } else {
      this.handleDetailPrint(true, false)
    }
  }

  async handleSaveSetting() {
    const api: Api = { method: 'post', url: `/api/v1/form/print/${this.formName}/modify` }
    const { dynamicSubTilteList, showTitle, title, showDynamicSubTitles, dynamicSubTiltes, showDate, showPageNum, showPrinter, showLogo, detailTableValues, showBarCode, showQRCode } = this.state
    const titleIndex = dynamicSubTiltes.map(val => dynamicSubTilteList.findIndex(title => val == title))
    const settingValues = {
      showTitle, title, showDynamicSubTitles, dynamicSubTiltes: titleIndex, showDate, showPageNum, showPrinter, showLogo, showQRCode, showBarCode,
      detailTableValues, reportTitleSql: this.reportTitleSql, reportSubTitleSql: this.reportSubTitleSql
    }
    this.setState({ saveLoading: true })
    const payload = await this.props.env.fetcher(api, settingValues).finally(() => { this.setState({ saveLoading: false }) })
    if (payload.ok) {
      message.success(payload.msg)
    }
  }

  async handleDeleteSetting() {
    const api: Api = { method: 'delete', url: `/api/v1/form/print/${this.formName}/delete` }
    const payload = await this.props.env.fetcher(api)
    if (payload.ok) {
      message.success(payload.msg)
    }
  }

  findLabel(name: string, object: any): { label: string } | undefined {
    if (typeof object == 'object') {
      if (Array.isArray(object)) {
        for (const item of object) {
          const target = this.findLabel(name, item)
          if (target) return target
        }
      }
      if (Object.prototype.hasOwnProperty.call(object, 'label') && Object.prototype.hasOwnProperty.call(object, 'content')) {
        const content = object['content']
        if (content['name'] === name) {
          return object
        }
      }
      for (const key in object) {
        if (Object.prototype.hasOwnProperty.call(object, key)) {
          const value = object[key];
          const target = this.findLabel(name, value)
          if (target) return target
        }
      }
    }
    return undefined
  }

  handleDetailPrint(preview: boolean, originalPrint: boolean) {
    const info = {
      originalPrint,
      printFlow: this.props.printInfo?.printFlow ?? false,
      title: this.state.title,
      subTitle: this.props.printInfo?.subTitle,
      extraTitle: this.props.printInfo?.extraTitle,
      dynamicSubTiltes: this.state.dynamicSubTiltes,
      showLogo: this.state.showLogo,
      showDate: this.state.showDate,
      showPrinter: this.state.showPrinter,
      scale: this.state.scale,
      tableSettings: this.state.detailTableValues
    }
    const codeField = this.props.codeField
    const label = this.findLabel(codeField, this.props.body)?.label ?? ''
    const setting: SettingValues = { ...this.state, content: 'all' }
    const options: DetailOptionValues & { subTitle?: string, extraTitle: string, codeLabel: string, codeValue: string } =
    {
      ...this.state,
      subTitle: this.props.printInfo?.subTitle,
      extraTitle: this.props.printInfo?.extraTitle ?? '',
      codeLabel: label,
      codeValue: this.props.data?.[codeField]
    }
    const template = buildDetailTemplate(setting, options)
    this.props.env.domPrint?.(document.getElementById(`FORM_${this.formName}`) ?? document.body, info)
    if (!originalPrint) {
      this.setState({ previewLoading: true, showEmpty: false })
      detailPrint(preview, setting, template, () => {
        if (!preview) message.success('打印任务发送成功')
        this.setState({ previewLoading: false })
      })
    }
  }

  handleTableValueChange(name: string, rowKey: number, columnKey: string, value: any) {
    this.setState(pre => ({
      detailTableValues: pre.detailTableValues.map(detail => {
        if (detail.name == name) {
          return {
            ...detail, columns: detail.columns.map((row, index) => {
              if (index == rowKey) {
                const tempRow = row
                tempRow[columnKey] = value
                return tempRow
              }
              return row
            })
          }
        }
        return detail
      })
    }))
  }

  handleTableChange(name: string, { isPrint, fontSize, fontFamily }: { isPrint?: boolean, fontSize?: number, fontFamily?: string }) {
    this.setState(pre => ({
      detailTableValues: pre.detailTableValues.map(detail => {
        if (detail.name == name) {
          return { ...detail, isPrint: isPrint ?? detail.isPrint, fontSize: fontSize ?? detail.fontSize, fontFamily: fontFamily ?? detail.fontFamily }
        }
        return detail
      })
    }))
  }

  render() {
    const { env, classnames: cx, translate: __, popupContainer, printers, onHide, superRole } = this.props
    const { previewLoading, showEmpty, isDynamicSubTitle, dynamicSubTilteList, detailTableValues } = this.state
    return (
      <>
        <div className={cx('Modal-header')}>
          <div className={cx('Modal-title')}>
            {'详情打印'}
            <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} />
              {showEmpty && <Empty description='暂无预览效果' className='preview-empty' />}
              <iframe id='detail-preview' width='100%' height='100%'></iframe>
            </div>
            <Tabs tabBarStyle={{ marginBottom: 8, paddingLeft: 24, paddingRight: 24 }} style={{ width: 350 }}>
              <Tabs.TabPane key={1} tab='设置'>
                <div className="print-setting">
                  <div className="print-setting-label">打印设备</div>
                  <div className="print-setting-content">
                    <Row gutter={10}>
                      <Col span={12}>
                        <Form.Item colon={false} label={__('CRUD.printer')} >
                          <Select
                            style={{ width: 170 }}
                            getPopupContainer={popupContainer}
                            dropdownClassName='label-print-selector'
                            value={this.state.printer}
                            onChange={value => this.setState({ printer: value })}
                          >
                            {printers.map(item => <Option key={item} value={item}>{item}</Option>)}
                          </Select>
                        </Form.Item>
                      </Col>
                      <Col span={12}>
                        <Form.Item colon={false} label={__('CRUD.pageSize')}  >
                          <Select
                            getPopupContainer={popupContainer}
                            dropdownClassName='label-print-selector'
                            value={this.state.page}
                            onChange={value => this.setState({ page: value, width: sizeOptions[value][0], height: sizeOptions[value][1] })}
                          >
                            {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 colon={false} label={__('width')}  >
                          <InputNumber style={{ width: 170 }} min={0} max={1000} value={this.state.width} onChange={value => value != null && this.setState({ width: value })} />
                        </Form.Item>
                      </Col>
                      <Col span={12}>
                        <Form.Item colon={false} label={__('height')}  >
                          <InputNumber style={{ width: 170 }} min={0} max={1000} value={this.state.height} onChange={value => value != null && this.setState({ height: value })} />
                        </Form.Item>
                      </Col>
                    </Row>
                  </div>
                  <div className="print-setting-label">纸张设置</div>
                  <div className="print-setting-content">
                    <Row gutter={10}>
                      <Col span={12}>
                        <Form.Item colon={false} label={__('up')} >
                          <InputNumber style={{ width: 170 }} min={0} max={100} value={this.state.top} onChange={value => value != null && this.setState({ top: value })} />
                        </Form.Item>
                      </Col>
                      <Col span={12}>
                        <Form.Item colon={false} label={__('below')} >
                          <InputNumber style={{ width: 170 }} min={0} max={100} value={this.state.bottom} onChange={value => value != null && this.setState({ bottom: value })} />
                        </Form.Item>
                      </Col>
                    </Row>
                    <Row gutter={10}>
                      <Col span={12}>
                        <Form.Item colon={false} label={__('left')} >
                          <InputNumber style={{ width: 170 }} min={0} max={100} value={this.state.left} onChange={value => value != null && this.setState({ left: value })} />
                        </Form.Item>
                      </Col>
                      <Col span={12}>
                        <Form.Item colon={false} label={__('right')} >
                          <InputNumber style={{ width: 170 }} min={0} max={100} value={this.state.right} onChange={value => value != null && this.setState({ right: value })} />
                        </Form.Item>
                      </Col>
                    </Row>
                    <Row >
                      <Col span={24}>
                        <Form.Item colon={false} label={__('direction')} >
                          <Radio.Group
                            value={this.state.direction}
                            onChange={value => this.setState({ direction: value.target.value })}
                          >
                            <Radio value={'vertical'}>{__('vertical')}</Radio>
                            <Radio value={'horizontal'}>{__('horizontal')}</Radio>
                          </Radio.Group>
                        </Form.Item>
                      </Col>
                    </Row>
                    <Row>
                      <Col span={24}>
                        <Form.Item colon={false} label={__('CRUD.copies')} >
                          <InputNumber style={{ width: 160 }} min={1} max={10} value={this.state.copies} onChange={value => value != null && this.setState({ copies: value })} />
                        </Form.Item>
                      </Col>
                    </Row>
                    <Row>
                      <Col span={24}>
                        <Form.Item colon={false} label={__('zoom')} >
                          <InputNumber style={{ width: 160 }} step={1} min={10} max={200} value={this.state.scale} onChange={value => value != null && this.setState({ scale: value })} />
                        </Form.Item>
                      </Col>
                    </Row>
                  </div>
                </div>
              </Tabs.TabPane>
              <Tabs.TabPane key={2} tab='选项'>
                <div className="print-setting">
                  <div className="print-setting-label">格式设置</div>
                  <div className="print-setting-content">
                    <Row align="middle" style={{ height: 32, marginBottom: 12 }} >
                      <Col span={8}>
                        <Checkbox checked={this.state.showTitle} onChange={e => this.setState({ showTitle: e.target.checked })}>打印标题</Checkbox>
                      </Col>
                      <Col span={16}>
                        <Input value={this.state.title} onChange={e => this.setState({ title: e.target.value })} maxLength={50} placeholder={__('CRUD.fillIn')} />
                      </Col>
                    </Row>
                    <Row align="middle" style={{ height: 32, marginBottom: 12 }} >
                      <Col span={8}>
                        <Checkbox checked={this.state.showDynamicSubTitles} onChange={e => this.setState({ showDynamicSubTitles: e.target.checked })}>打印子标题</Checkbox>
                      </Col>
                      <Col span={16}>
                        {isDynamicSubTitle ?
                          <Select
                            style={{ width: '100%' }}
                            getPopupContainer={popupContainer}
                            dropdownClassName='label-print-selector'
                            mode="multiple"
                            placeholder={__('Select.placeholder')}
                            maxTagCount='responsive'
                            value={this.state.dynamicSubTiltes}
                            onChange={value => {
                              if (value.length <= 3) {
                                this.setState({ dynamicSubTiltes: value })
                              } else {
                                env.notify('error', '最多选择3项')
                              }
                            }}
                          >
                            {dynamicSubTilteList.map((item, index) => <Option key={index} value={item}>{item}</Option>)}
                          </Select> :
                          <Input value={this.state.dynamicSubTiltes[0]} onChange={e => this.setState({ dynamicSubTiltes: [e.target.value] })} maxLength={50} placeholder={__('CRUD.fillIn')} />
                        }
                      </Col>
                    </Row>
                  </div>
                  <div className="print-setting-label">内容设置</div>
                  <div className="print-setting-content">
                    <Row align="middle" style={{ height: 32, marginBottom: 8 }}>
                      <Col span={12}><Checkbox checked={this.state.showDate} onChange={e => this.setState({ showDate: e.target.checked })}>打印日期</Checkbox></Col>
                      <Col span={12}><Checkbox checked={this.state.showLogo} onChange={e => this.setState({ showLogo: e.target.checked })}>公司标记</Checkbox></Col>
                    </Row>
                    <Row align="middle" style={{ height: 32, marginBottom: 8 }}>
                      <Col span={12}><Checkbox checked={this.state.showPageNum} onChange={e => this.setState({ showPageNum: e.target.checked })}>页码</Checkbox></Col>
                      <Col span={12}><Checkbox checked={this.state.showPrinter} onChange={e => this.setState({ showPrinter: e.target.checked })}>打印者</Checkbox></Col>
                    </Row>
                    <Row align="middle" style={{ height: 32, marginBottom: 8 }}>
                      <Col span={12}>
                        <Checkbox
                          checked={this.state.showBarCode}
                          onChange={e => {
                            const checked = e.target.checked
                            this.setState(pre => ({ showBarCode: checked, showQRCode: checked ? false : pre.showQRCode }))
                          }}
                        >
                          打印条码
                        </Checkbox>
                      </Col>
                      <Col span={12}>
                        <Checkbox
                          checked={this.state.showQRCode}
                          onChange={e => {
                            const checked = e.target.checked
                            this.setState(pre => ({ showQRCode: checked, showBarCode: checked ? false : pre.showBarCode }))
                          }}
                        >
                          打印二维码
                        </Checkbox>
                      </Col>
                    </Row>
                  </div>
                </div>
              </Tabs.TabPane>
              <Tabs.TabPane key={3} tab='数据' style={{ height: '100%' }}>
                <div style={{ width: '100%', height: '100%', overflowY: 'auto' }}>
                  {detailTableValues.map(detail => {
                    const id = `report-print-column-config-table_${detail.name}`
                    return (
                      <div key={detail.name} style={{ marginBottom: 8 }}>
                        <Checkbox checked={detail.isPrint} onChange={e => this.handleTableChange(detail.name, { isPrint: e.target.checked })}>{detail.label || `表格${detail.name}`}</Checkbox>
                        <div style={{ marginTop: 3 }}>
                          <span>字体：</span>
                          <Select style={{ width: 100 }} size='small' value={detail.fontFamily} onChange={val => this.handleTableChange(detail.name, { fontFamily: val })} >
                            <Option value={'宋体'}>宋体</Option>
                            <Option value={'微软雅黑'}>微软雅黑</Option>
                            <Option value={'楷体'}>楷体</Option>
                          </Select>
                          <span>&nbsp;&nbsp;字号：</span>
                          <Select style={{ width: 100 }} size='small' value={detail.fontSize} onChange={val => this.handleTableChange(detail.name, { fontSize: val })} >
                            <Option value={12}>12px</Option>
                            <Option value={15}>15px</Option>
                            <Option value={18}>18px</Option>
                            <Option value={21}>21px</Option>
                          </Select>
                        </div>
                        <table style={{ marginTop: 8 }} id={id} className="column-config-table" width={300} cellSpacing={0} >
                          <thead>
                            <tr>
                              {tableColumns.map(column => (<th key={column.key} >{column.title}</th>))}
                            </tr>
                          </thead>
                          <tbody>
                            {detail.columns.map((row, index) => (
                              <tr key={index}>
                                {tableColumns.map(column => (
                                  <td key={column.key}>
                                    {column.type == 'text' && <>{row.title}</>}
                                    {column.type == 'select' &&
                                      <Select
                                        size='small'
                                        showArrow={false}
                                        value={row[column.key]}
                                        getPopupContainer={() => document.getElementById(id)!}
                                        dropdownClassName='column-config-table-select-dropdown'
                                        onChange={value => { this.handleTableValueChange(detail.name, index, column.key, value) }}
                                      >
                                        {column.options!.map((option, index) => (
                                          <Option key={index} value={option.value}>
                                            {option.label}
                                          </Option>
                                        ))}
                                      </Select>
                                    }
                                  </td>
                                ))}
                              </tr>
                            ))}
                          </tbody>
                        </table>
                      </div>
                    )
                  })}
                </div>
              </Tabs.TabPane>
            </Tabs>
          </div>
        </div>
        <div className={cx('Modal-footer')} >
          {superRole && <Button onClick={() => this.handleDeleteSetting()}>清空默认值</Button>}
          {superRole && <Button onClick={() => this.handleSaveSetting()} loading={this.state.saveLoading}>设置默认值</Button>}
          {this.showDebugPreviewButton && <Button onClick={this.handleDetailPrint.bind(this, true, true)} >预览</Button>}
          <Button level="primary" onClick={this.handleDetailPrint.bind(this, true, false)} >{__('preview')}</Button>
          <Button level="primary" onClick={this.handleDetailPrint.bind(this, false, false)} >{__('print')}</Button>
          <Button onClick={(e: any) => onHide(e)}>{__('cancel')}</Button>
        </div >
      </>
    )
  }
}

