import React from "react"
import { Modal, Button, Row, Col, Spin, Tree, Input, Tooltip, Typography, Select, Pagination, Space } from 'antd'
import produce from 'immer'
import { useDebounceEffect } from "ahooks"
import classnames from 'classnames'

import Table from '../../ResizeableTable'
import { dispatch } from '../../../../model'
import { AssetItem } from "../../AssetManage/Component/AssetTable"
import IframeDrawer from '../../ModelConfig/Component/IframeDrawer';
import { Action, CatalogId, MetadataId } from "../../../../util/constant"
import { showMessage } from "../../../../util"

const FC = ({ visible, catalogId, onCancel }) => {
  const [animated, setAnimated] = React.useState(true)
  const [waiting, setWaiting] = React.useState(false)
  const [iframeDrawerParams, setIframeDrawerParams] = React.useState({
    visible: false,
    title: undefined,
    url: undefined,
  })
  
  const basicRef = React.useRef()

  React.useEffect(() => {
    if (visible) {
      setTimeout(() => {
        setAnimated(false)
      }, 300)
    }
  }, [visible])

  const close = () => {
    setAnimated(true)
    onCancel?.()
  }

  const save = async () => {
    const selectedRows = basicRef.current?.selectedRows
    if ((selectedRows??[]).length === 0) {
      showMessage('warn', '请选择资产')
    } else {
      const asset = selectedRows[0]
      console.log('asset', asset)
      const metadataTableId = asset['资产项'].metadataTableId
      if (metadataTableId) {
        dispatch({
          type: 'datamodel.getDraftUsingMetadataId',
          payload: {
            params: {
              dataCatalogId: catalogId,
            },
            data: {
              metadataTableId: metadataTableId,
              modelerModelingConstraint: null,
              easyDataModelerModelingTemplate: {}, 
            }   
          },
          callback: data => {
            setIframeDrawerParams({
              visible: true,
              title: '新增模型',
              url: `/data-govern/data-model-action?${Action}=add&${MetadataId}=${metadataTableId}&${CatalogId}=${catalogId??''}`,
            })
          }
        });
      } else {
        showMessage('warn', '选中资产没有关联元数据')
      }
    }
  }

  const footer = React.useMemo(() => {
    return [
      <Button key='cancel'
        onClick={() => close()}
      >取消</Button>,
      <Button key='save' type='primary'
        onClick={() => save()}
      >确定</Button>
    ]
  }, [close, save])

  return (
    <>
    <Modal
      title='选择资产'
      visible={visible}
      footer={footer}
      width='80%'
      bodyStyle={{ padding: '15px', overflowX: 'auto', height: '80vh' }}
      centered destroyOnClose
      onCancel={() => { close() }}
    >
      {
        !animated && <Basic ref={basicRef} />
      }
    </Modal>
    { iframeDrawerParams.visible && <IframeDrawer
      {...iframeDrawerParams}
      onCancel={() => {
        setIframeDrawerParams({
          visible: false,
          title: undefined,
          url: undefined,
        })
      }}
    /> }
    </>
  )
}

export default FC

const Basic = React.forwardRef(function ({}, ref) {
  const [args, setArgs] = React.useState(() => ({
    page: 1, 
    size: 20,
    keyword: undefined,
  }))
  const [loadingTreeData, setLoadingTreeData] = React.useState(false)
  const [treeData, setTreeData] = React.useState()
  const [node, setNode] = React.useState()

  const [loadingTemplates, setLoadingTemplates] = React.useState(false)
  const [loading, setLoading] = React.useState(false)
  const [loadingElements, setLoadingElements] = React.useState(false)
  const [templates, setTemplates] = React.useState()
  const [elements, setElements] = React.useState()
  const [data, setData] = React.useState()
  const [currentTemplate, setCurrentTemplate] = React.useState()
  const [selectedRows, setSelectedRows] = React.useState([])
  const [expandedKeys, setExpandedKeys] = React.useState([])
  const [autoExpandParent, setAutoExpandParent] = React.useState(false)
  const [users, setUsers] = React.useState()
  const [detailParams, setDetailParams] = React.useState({
    visible: false,
    id: undefined,
    dirId: undefined,
  })

  React.useImperativeHandle(ref, () => ({
    selectedRows
  }), [selectedRows])

  React.useEffect(() => {
    getUsers()
    getTemplates()
  }, [])

  React.useEffect(() => {
    if (currentTemplate) {
      getTreeData()
      getElements()
    }
  }, [currentTemplate])

  React.useEffect(() => {
    if (currentTemplate && node) {
      setSelectedRows()
      setArgsByParams({ page: 1 })
    }
  }, [currentTemplate, node])

  useDebounceEffect(() => {
    if (currentTemplate) {
      getAssets()
    }
  }, [args], { wait: 300 })

  const treeData1 = React.useMemo(() => {
    if (treeData) {
      const newTreeData = produce(treeData, draft => {
        const setNode = (g) => {
          g.key = g.nodeId
          g.title = `${g.text} (${g.dataAssetAndSubDirCount})`
          g.children?.forEach((child) => {
            setNode(child)
          })
        }

        draft.forEach((child) => {
          setNode(child)
        })
      })

      return newTreeData
    }

    return undefined
  }, [treeData])

  const [columns, tableData, total] = React.useMemo(() => {
    let [newColumns, newTableData] = [[], []]

    for (const element of elements??[]) {
      for (const name of element.names??[]) {
        const column = {
          title: name,
          dataIndex: name,
          ellipsis: true,
          render: (text, record) => {
            return (
              <Tooltip title={text}>
                <Typography.Text ellipsis={true}>
                {text}
                </Typography.Text>
              </Tooltip>
            );
          }
        }

        if (name === '资产项') {
          column.width = 250
          column.render = (text) => {
            return (
              <AssetItem metadata={text} />
            );
          }
        }

        newColumns.push(column)
      }
    }

    if (!loadingElements) {
      for (const item of (data?.data??[])) {
        let index = 0
        let newItem = {}
        for (const elementValue of (item.elementValues??[])) {
          for (const value of elementValue.values) {
            if ((newColumns??[]).length > index) {
              const name = newColumns[index].dataIndex
              newItem[name] = value

              if (name === '资产项') {
                let metadata = null
                try {
                  metadata = JSON.parse(value)
                } catch(error) {
                  metadata = value;
                }

                newItem[name] = metadata
              }
            }
  
            index++
          }
        }
  
        newTableData.push({...item, ...newItem})
      }
    }

    return [newColumns, newTableData, data?.total??0]
  }, [elements, data, loadingElements, users])

  const setArgsByParams = React.useCallback((params) => {
    setArgs((prev) => {
      return {...prev, ...params}
    })
  }, [])

  const getUsers = () => {
    dispatch({
      type: 'pds.getOwners',
      callback: (data) => {
        setUsers(data)
      }
    })
  }

  const getTemplates = () => {
    setLoadingTemplates(true)

    dispatch({
      type: 'assetmanage.getTemplates',
      callback: data => {
        setLoadingTemplates(false)
        setTemplates(data)
  
        if ((data??[]).length > 0) {
          setCurrentTemplate(data[0])
        }
      },
      error: () => {
        setLoadingTemplates(false)
      }
    })
  }

  const getTreeData = () => {
    setLoadingTreeData(true)
    dispatch({
      type: 'assetmanage.queryAllDirectoryAsTree',
      payload: {
        templateType: currentTemplate?.type
      },
      callback: data => {
        setLoadingTreeData(false)
        setTreeData(data)
        if ((data??[]).length>0) {
          setNode(data[0])
        }
      },
      error: () => {
        setLoadingTreeData(false)
      }
    }) 
  }

  const getElements = () => {
    setLoadingElements(true)
    dispatch({
      type: 'assetmanage.listFilterElementsGroupByType',
      payload: {
        templateType: currentTemplate?.type,
        isAdmin: false
      },
      callback: data => {
        setLoadingElements(false)
        setElements(data)
      },
      error: () => {
        setLoadingElements(false)
      }
    }) 
  }

  const getAssets = () => {
    setLoading(true)
    dispatch({
      type: 'assetmanage.listDataAssetsByPage',
      payload: {
        dirId: node?.nodeId??'',
        pageNum: args.page,
        pageSize: args.size,
        keyword: args.keyword??'',
        recursive: true,
        templateType: currentTemplate?.type,
        checkPermission: true,
      },
      callback: data => {
        setLoading(false)
        setData(data)
      },
      error: () => {
        setLoading(false)
      }
    })
  }

  const onTreeExpand = (expandedKeys) => {
    setExpandedKeys(expandedKeys)
    setAutoExpandParent(false)
  }

  const onTreeSelect = (selectedKeys, { selectedNodes }) => {
    if (selectedKeys.length === 0 || selectedNodes.length === 0) {
      return
    }

    setNode(selectedNodes[0])
  }

  return (
    <div className='post-select-asset'>
      <Row>
        <Col span={4}>
          <Select
            size='small'
            loading={loadingTemplates}
            value={currentTemplate?.type}
            onChange={(val) => {
              if (val) {
                const index = (templates??[]).findIndex(item => item.type === val)
                if (index !== -1) {
                  setCurrentTemplate(templates[index])
                  setNode()
                } else {
                  setCurrentTemplate()
                  setNode()
                }
              } else {
                setCurrentTemplate()
                setNode()
              }
            }}
            style={{ width: 100, marginBottom: 10 }}
          >
            {(templates??[]).map(item => (
              <Select.Option key={item.id} value={item.type}>{item.name}</Select.Option>
            ))}
          </Select>
          <Spin spinning={loadingTreeData}>
            <Tree
              className='tree'
              showLine 
              showIcon={false} 
              autoExpandParent={autoExpandParent}
              treeData={treeData1}
              selectedKeys={node?[node.nodeId]:[]}
              expandedKeys={expandedKeys}
              onSelect={onTreeSelect}
              onExpand={onTreeExpand}
            />
          </Spin>
        </Col>
        <Col span={20}>
          <div
            style={{
              display: 'flex',
              padding: '0px 0px 15px',
              alignItems: 'center',
              justifyContent: 'flex-end',
            }}>
            <Input size="middle"
              placeholder="请输入资产目录要素值"
              value={args.keyword}
              bordered={true} allowClear
              onChange={(e) => {
                setArgsByParams({ keyword: e.target.value, page: 1 })
              }} 
              style={{ width: 200 }}
            />
          </div>
          <Table
            size='small'
            rowKey='id'
            extraColWidth={32}
            loading={loading||loadingElements}
            columns={columns}
            dataSource={tableData}
            pagination={false}
            rowSelection={{
              type: 'radio',
              selectedRowKeys: (selectedRows??[]).map(item => item.id),
              onChange: (selectedRowKeys, selectedRows) => {
                console.log('selected rows', selectedRows)
                setSelectedRows(selectedRows)
              },
            }}
            scroll={{ y: 'calc(80vh - 170px)' }}
          />
          {
            (total!==0) && <Pagination
              style={{
                textAlign: 'center',
                marginTop: 15,
              }}
              showSizeChanger
              onChange={(page,size) => {
                setArgsByParams({ page, size })
              }}
              current={args.page}
              pageSize={args.size}
              defaultCurrent={1}
              total={total}
              showTotal={() => `共${total??0}项`}
            />
          }
        </Col>
      </Row>
    </div>
  )
})