import React, { useEffect, useRef, useState } from 'react'
import Checkbox from 'antd/lib/checkbox/Checkbox';
import AntdButton from 'antd/lib/button'
import { Col, Row } from 'antd/lib/grid';
import Radio from 'antd/lib/radio';
import Modal from 'antd/lib/modal/Modal';
import message from 'antd/lib/message'
import { Action } from '../../types';
import { Button } from '../../components';
import { Icon } from '../../components/icons';
import { IColumn } from '../../store/table';
import { ICross, buildCrossColumn, buildCrossColumn1, ICrossColumn } from './cross';
import { CountItem } from '.';
import { flatMap } from 'lodash';
import './dataStatic.scss';

interface IProps {
  tableName: string
  action: Action
  columns: IColumn[]
  data: { items: any[], selectedItems: any[] }
  modalContainer: HTMLDivElement | null
  getAllData: () => Promise<{ items: any[], total: number }>
  onOK: (cross: ICross, crossColumns: ICrossColumn[], datas: any[], countColumns: CountItem[]) => void
}

type CrossData = {
  rowFields: FieldType[],
  colFields: FieldType[],
  valueFields: FieldType[],
  dataRange: 0 | 1 | 2
  countSum: boolean
  valuePosition: 'row' | 'col'
}

interface FieldType extends IColumn {
  name: string
  label: string
  checked: boolean
  hidden: boolean
}

const DataCross: React.FC<{ tableName: string, columns: IColumn[], onChange: (data: CrossData) => void }> = ({ tableName, columns, onChange }) => {

  const initFields = (type: 0 | 1 | 2): FieldType[] => {
    return columns.filter(column => {
      if (column.name) {
        if (type == 0 || type == 1) {
          return column.type == 'plain' || column.type == 'number' || column.type == 'date' || column.type == 'progress' || column.type == 'color' || column.type == 'mapping'
        } else {
          const dataTypeArr = ['number', 'static-number', 'input-number', 'progress', 'static-progress']
          return column.pristine.isNumerical || dataTypeArr.includes(column.type)
        }
      }
      return false
    }).map(column => ({
      ...column,
      name: column.name!,
      label: column.groupName.length > 0 ? `${column.groupName}·${column.label}` : String(column.label),
      checked: false,
      hidden: false
    }))
  }

  const [rowFields, setRowFields] = useState<FieldType[]>(() => initFields(0))

  const [colFields, setColFields] = useState<FieldType[]>(() => initFields(1))

  const [valueFields, setValueFields] = useState<FieldType[]>(() => initFields(2))

  const [dataRange, setDataRange] = useState<0 | 1 | 2>(0)

  const [countSum, setCountSum] = useState(false)

  const [valuePosition, setValuePosition] = useState<'row' | 'col'>('row')

  useEffect(() => {
    getDefaultValues()
  }, [])

  useEffect(() => {
    onChange({ rowFields, colFields, valueFields, dataRange, countSum, valuePosition })
  }, [rowFields, colFields, valueFields, dataRange, countSum, valuePosition])

  const getDefaultValues = () => {
    const value = localStorage.getItem(`cross_${tableName}`) ?? '{}'
    const obj = JSON.parse(value)
    const { rowFields: rowFieldNames, colFields: colFieldNames, valueFields: valueFieldNames, dataRange, countSum = false, valuePosition = 'row' } = obj
    if (Array.isArray(rowFieldNames)) {
      handleChange(0, rowFieldNames.map(name => ({ name, checked: true })))
    }
    if (Array.isArray(colFieldNames)) {
      handleChange(1, colFieldNames.map(name => ({ name, checked: true })))
    }
    if (Array.isArray(valueFieldNames)) {
      handleChange(2, valueFieldNames.map(name => ({ name, checked: true })))
    }
    if (dataRange) {
      setDataRange(dataRange)
    }
    setCountSum(countSum)
    setValuePosition(valuePosition)
  }

  const handleChange = (type: 0 | 1 | 2, items: { name: string, checked: boolean }[]) => {
    const checkFn = (datas: FieldType[]) => {
      return datas.map(data => {
        const target = items.find(item => item.name == data.name)
        return target ? { ...data, checked: target.checked } : data
      })
    }
    const hideFn = (datas: FieldType[]) => {
      return datas.map(data => {
        const target = items.find(item => item.name == data.name)
        return target ? { ...data, hidden: target.checked } : data
      })
    }
    if (type == 0) {
      setRowFields(checkFn)
      setColFields(hideFn)
      setValueFields(hideFn)
    } else if (type == 1) {
      setColFields(checkFn)
      setRowFields(hideFn)
      setValueFields(hideFn)
    } else if (type == 2) {
      setValueFields(checkFn)
      setRowFields(hideFn)
      setColFields(hideFn)
    }
  }

  const renderItem = (type: 0 | 1 | 2, datas: FieldType[]) => {
    return (
      <div className="common-select-container" style={{ height: '100%', width: 'calc(33% - 8px)' }}>
        <div className="sel-top">
          <span>{type == 0 ? '行' : type == 1 ? '列' : '值'}</span>
          <div className='sel-btn-group'>
            <span className="btn" onClick={() => handleChange(type, datas.filter(data => !data.hidden).map(data => ({ name: data.name, checked: true })))}>全选</span>
            <span className="btn" onClick={() => handleChange(type, datas.filter(data => !data.hidden).map(data => ({ name: data.name, checked: !data.checked })))}>反选</span>
            <span className="btn" onClick={() => handleChange(type, datas.filter(data => !data.hidden).map(data => ({ name: data.name, checked: false })))}>不选</span>
          </div>
        </div>
        <div className="sel-body" style={{ padding: '6px 10px', height: 420, overflow: 'auto' }}>
          {datas.map((item) => (
            <div key={item.name} className="checkbox-container">
              {!item.hidden && <Checkbox key={item.name} checked={item.checked} onChange={e => handleChange(type, [{ name: item.name, checked: e.target.checked }])}>{item.label}</Checkbox>}
            </div>
          ))}
        </div>
      </div>
    )
  }

  return (
    <>
      <div className="select-wrapper-group-container" >
        {renderItem(0, rowFields)}
        {renderItem(1, colFields)}
        {renderItem(2, valueFields)}
      </div>
      <Row style={{ marginTop: 12 }}>
        <Col span={4} >
          <span>数据范围</span>
        </Col>
        <Col span={13}>
          <Radio.Group onChange={e => setDataRange(e.target.value)} value={dataRange}>
            <Radio value={0}>当前页数据</Radio>
            <Radio value={1}>选中数据</Radio>
            <Radio value={2}>全部数据</Radio>
          </Radio.Group>
        </Col>
        <Col span={3}>
          <Checkbox checked={valuePosition == 'col'} onChange={e => setValuePosition(e.target.checked ? 'col' : 'row')} >转置</Checkbox>
        </Col>
        <Col span={4}>
          <Checkbox checked={countSum} onChange={e => setCountSum(e.target.checked)} >生成合计值</Checkbox>
        </Col>
      </Row>
    </>

  )
}

export default (props: IProps) => {

  const { tableName, action, columns, data, modalContainer, getAllData, onOK } = props

  const [visible, setVisible] = useState(false)

  const [confirmLoading, setConfirmLoading] = useState(false)

  const crossDataRef = useRef<CrossData>()

  const getData = async (dataRange: 0 | 1 | 2) => {
    if (dataRange == 0) {
      return Promise.resolve(data.items)
    } else if (dataRange == 1) {
      return Promise.resolve(data.selectedItems)
    } else {
      const { items } = await getAllData()
      if (Array.isArray(items)) {
        return items
      }
      return []
    }
  }

  const handleOk = async () => {
    if (crossDataRef.current) {
      const rowFields = crossDataRef.current.rowFields.filter(field => !field.hidden && field.checked)
      const colFields = crossDataRef.current.colFields.filter(field => !field.hidden && field.checked)
      const valueFields = crossDataRef.current.valueFields.filter(field => !field.hidden && field.checked)
      if (valueFields.length == 0) {
        message.warning('请选择值')
        return
      }
      const dataRange = crossDataRef.current.dataRange
      const countSum = crossDataRef.current.countSum
      const valueInCol = crossDataRef.current.valuePosition == 'col'
      setConfirmLoading(true)
      const [crossColumns, datas] = await getData(dataRange).then<[ICrossColumn[], any[]]>(async datas => {
        if (datas.length > 10000) {
          message.warning('数据行数大于10000条，请重新选择')
          return [[], []]
        }
        const crossColumns = valueInCol ? buildCrossColumn1(rowFields, colFields, datas) : buildCrossColumn(rowFields, colFields, valueFields, datas, countSum)
        if (crossColumns.length > 1000) {
          message.warning('交叉制表结果列数大于1000，请重新选择')
          return [[], []]
        }
        return [crossColumns, datas]
      }).catch<[ICrossColumn[], any[]]>(() => [[], []]).finally(() => { setConfirmLoading(false) })

      if (crossColumns.length > 0) {
        localStorage.setItem('Debug_rowFields', JSON.stringify(rowFields.map(field => ({ label: field.label, name: field.name }))))
        localStorage.setItem('Debug_rawColumns', JSON.stringify(columns.map(column => ({ label: column.label, name: column.name }))))
        localStorage.setItem('Debug_retColumns', JSON.stringify(crossColumns.map(column => ({ label: column.label, name: column.name }))))

        setVisible(false)
        const cross: ICross = {
          columnFields: colFields.map(field => ({ name: field.name })),
          rowFields: rowFields.map(field => ({ name: field.name })),
          valueFields: valueFields.map(field => field.name).join(','),
          positionType: valueInCol ? 1 : 0
        }
        const countColumns: CountItem[] = countSum ? valueFields.map(field => ({ name: field.name, label: field.label, formula: 'SUM', type: 'formula', rule: '合计' })) : []
        onOK(cross, crossColumns, datas, countColumns)
      }
    }
  }

  const handleDefault = () => {
    if (crossDataRef.current && tableName) {
      const rowFields = flatMap(crossDataRef.current.rowFields ?? [], field => !field.hidden && field.checked ? field.name : [])
      const colFields = flatMap(crossDataRef.current.colFields ?? [], field => !field.hidden && field.checked ? field.name : [])
      const valueFields = flatMap(crossDataRef.current.valueFields ?? [], field => !field.hidden && field.checked ? field.name : [])
      const value = JSON.stringify({ ...crossDataRef.current, rowFields, colFields, valueFields })
      localStorage.setItem(`cross_${tableName}`, value)
      message.success('保存成功')
    }
  }

  const renderFooter = () => {
    return (
      <div>
        <AntdButton style={{ float: 'left', borderRadius: 4 }} onClick={handleDefault}>设置默认</AntdButton>
        <AntdButton style={{ borderRadius: 4 }} onClick={() => setVisible(false)}>取消</AntdButton>
        <AntdButton style={{ borderRadius: 4 }} type='primary' loading={confirmLoading} onClick={handleOk}>确定</AntdButton>
      </div>
    )
  }

  return (
    <>
      <Button onClick={() => { setVisible(true) }}>
        <Icon icon={action.icon ?? "#icon-tooltool_autowidth"} className="icon" symbol />
        {action.label}
      </Button>
      <Modal
        title='交叉制表'
        className={'statics-modal'}
        bodyStyle={{ maxHeight: 'calc(100vh - 220px) !important' }}
        width={773}
        visible={visible}
        okText='确定'
        cancelText='取消'
        centered={true}
        destroyOnClose={true}
        maskClosable={false}
        confirmLoading={confirmLoading}
        cancelButtonProps={{ disabled: confirmLoading }}
        getContainer={modalContainer ?? document.body}
        onCancel={() => setVisible(false)}
        footer={renderFooter()}
      >
        <DataCross tableName={tableName} columns={columns} onChange={data => crossDataRef.current = data} />
      </Modal>
    </>
  )

}
