/* eslint-disable no-restricted-syntax */
import { Space, Table, Button, Popconfirm, notification, Spin, Input, Radio, message } from 'antd';
import React, { useState, useEffect } from 'react';
import styles from '../SchemeConfig.less';
import {
  GetVectorService,
  deleteVectorService,
  getSolutionList,
  updatePublishedMetaData,
  GettMaplayer,
  deleteConfig,
  GetFileContent,
  getAllMetaData,
  AddStyleConfigJson
} from '@/services/webConfig/api';
import { LayerSetting } from '@/services/gis/gis';
import AddModal from './AddModal';
import PreviewModal from './VectorPreviewModal';
import MeteDataModal from './MeteDataModal';
import AddSlicedModal from './AddSlicedModal';
import { mapConfig , VectorUtils} from '@wisdom-map/gis-utils'
import {parseUrlQueryParams , queryParamsToUrl} from '@/utils/utils'

const VectorData = props => {
  const [treeLoading, setTreeLoading] = useState(false); // 弹窗显示
  const [tileData, setTileData] = useState([]); // table表格数据
  const [tileSlicedData, setTileSlicedData] = useState([]);
  const [visible, setVisible] = useState(false); // 弹窗
  const [previewVisible, setPreviewVisible] = useState(false); // 预览弹窗
  const [meteDataVisible, setMeteDataVisible] = useState(false); // 预览弹窗
  const [flag, setFlag] = useState(0); // 更新list
  const [loading, setLoading] = useState([]); // 更新状态
  const [allLoading, setAllLoading] = useState(false); // 更新状态
  const [type, setType] = useState(''); // 弹窗类型
  const [solutionNames, setSolutionNames] = useState('');
  const [formObj, setFormObj] = useState({ user: 'admin', password: 'panda_server@2023' });
  const [record, setRecord] = useState();
  const [currentMetaData, setCurrentMetaData] = useState(null);
  const [searchValue, setSearchValue] = useState('');
  const [radioType, setRadioType] = useState('1');
  const [addVisible, setAddVisible] = useState(false); // 弹窗
  const [treeTileLoading, setTreeTileLoading] = useState(false);
  const [name, setName] = useState([]);
  const { Search } = Input;
  const columns = [
    {
      title: '服务名',
      dataIndex: 'ServiceName',
      key: 'ServiceName',
      align: 'center',
    },
    {
      title: 'IP',
      dataIndex: 'GISServerIP',
      key: 'GISServerIP',
      align: 'center',
    },
    {
      title: '端口',
      dataIndex: 'GISServerPort',
      key: 'GISServerPort',
      align: 'center',
    },
    {
      title: '工程名',
      dataIndex: 'GISServerProjectName',
      key: 'GISServerProjectName',
      align: 'center',
    },
    {
      title: '发布时间',
      dataIndex: 'PublishTime',
      key: 'PublishTime',
      align: 'center',
    },
    {
      title: '编辑',
      align: 'center',
      width: 260,
      render: (text, record, index) => (
        <Space>
          <Button type="primary" size="small" onClick={() => metadata(record)}>
            元数据
          </Button>
          <Button type="primary" size="small" onClick={() => previewMetaData(record, index)}>
            预览
          </Button>
          <Button
            type="primary"
            size="small"
            loading={loading[index] || allLoading}
            onClick={() => enterLoading(record, index)}
          >
            更新
          </Button>
          <div onClick={e => e.stopPropagation()}>
            <Popconfirm
              title="是否删除该矢量数据?"
              okText="确认"
              cancelText="取消"
              onConfirm={() => {
                delConfirm(record);
              }}
            >
              <Button size="small" danger>
                删除
              </Button>
            </Popconfirm>
          </div>
        </Space>
      ),
    },
  ];
  const columnsPart = [
    {
      title: '服务名',
      dataIndex: 'servicename',
      key: 'servicename',
      align: 'center',
    },
    {
      title: '标签',
      dataIndex: 'label',
      key: 'label',
      align: 'center',
    },
    {
      title: '类型',
      dataIndex: 'type',
      key: 'type',
      align: 'center',
    },
    {
      title: '编辑',
      align: 'center',
      render: (text, record) => (
        <Space>
          <Button
            type="primary"
            size="small"
            onClick={() => {
              changebaseMap(record);
            }}
          >
            编辑
          </Button>
          <div onClick={e => e.stopPropagation()}>
            <Popconfirm
              title="是否删除该切片管网?"
              okText="确认"
              cancelText="取消"
              onConfirm={() => {
                delConfirmSliced(record);
              }}
            >
              <Button size="small" danger>
                删除
              </Button>
            </Popconfirm>
          </div>
        </Space>
      ),
    },
  ];
  // 更新
  const enterLoading = (record, index) => {
    const newLoadings = [...loading];
    newLoadings[index] = true;
    setLoading(newLoadings);
    let query = {
      serviceName: record.ServiceName,
      _version: 9999,
      solution: solutionNames,
    };

    updatePublishedMetaData(query)
      .then(res => {
        const newLoadings = [...loading];
        newLoadings[index] = false;
        setLoading(newLoadings);
        if (res.success) {
          updateVectorConfig({
            mapServerName : record['ServiceName']
          })
          setFlag(flag + 1);
          notification.success({
            message: '提示',
            duration: 3,
            description: '更新元数据成功',
          });
        } else {
          notification.error({
            message: '提示',
            duration: 3,
            description: '更新元数据失败',
          });
        }
      })
      .catch(err => {
        const newLoadings = [...loading];
        newLoadings[index] = false;
        setLoading(newLoadings);
        notification.error({
          message: '提示',
          duration: 3,
          description: '服务无法访问',
        });
      });
  };
  const updateVectorConfig = async ({
    mapServerName
  }) => {
    try {
      const schemes = await updateCurrentMapschemes({mapServerName, exportScheme :  mapConfig.exportScheme.arcgis})
      if(schemes.length == 0) return
      const vectorData = await getVectorConfigData({
        schemes,
        mapServerName
      })
      if(!vectorData) return 
      const metaData = await getMetaData({mapServerName})
      if(!metaData) return
      let isChange = handleDataLayer({
        schemes,
        vectorData,
        metaData
      })
      const isFilterField = getDataIsFilterField({
        schemes,
        vectorData
      })
      if(isFilterField) {
        const isUpdateFile = updateVectorFileds({
          metaData,
          schemes,
          vectorData
        })
        if(isUpdateFile) {
          isChange = true
        }
      }
      if(isChange) {
        const result = await AddStyleConfigJson({
          fileName : "StyleConfig",
          preventCache : Date.now()
        }, vectorData)
      }
    } catch (error) {
      console.log(error)
    }
  }

  const updateCurrentMapschemes = async ({mapServerName, exportScheme}) => {
    const data = await LayerSetting({client : "sandbox"})
    if(data.code == "0") {
      return data.data.filter(item => item.id == mapServerName && 
        (
          exportScheme ?  item.exportScheme == mapConfig.exportScheme.arcgis : true
        )
      )
    }
    return []
  }

  const getVectorConfigData = async () => {
    const data = await GetFileContent({
      path : "StyleConfig/StyleConfig.json",
      preventCache : Date.now()
    })
    if(data.code == "0" && data.data.data && data.data.hasOwnProperty("version")) {
      return data.data
    } 
    return null
  }

  const handleDataLayer = ({
    schemes,
    vectorData,
    metaData
  }) => {
    let isChange = false
    schemes.map(scheme => {
      const data = vectorData.data[`${scheme.schemename}-${scheme.id}`]
      data.map(item => {
        const {params, url} = parseUrlQueryParams({
          url : item.style.sources.osm.tiles[0]
        })
        const layerNameArr = params.layerNames.split(",")
        const outfields = params.outfields.split(";")
        if(layerNameArr.length != outfields.length) return
        const newLayerNameArr = [], deleteIndexArr = []
        for(let i = 0; i < item.style.layers.length ; i++) {
          const layer = item.style.layers[i]
          const hasLayer = metaData.find(item => item.name == layer['source-layer'])
          if(hasLayer) {
            !newLayerNameArr.includes(hasLayer.name) && newLayerNameArr.push(hasLayer.name)
          } else {
          }
        }
        if(newLayerNameArr.length == layerNameArr.length) return
        isChange = true
        const newOutfields = newLayerNameArr.map(name => {
          const index = layerNameArr.findIndex(a => a == name)
          if(index == -1) {
            const outFiled =  getLayerFilterOutFields({
              item,
              name,
              metaLayer : metaData.find(item => item.name == name)
            })
            return outFiled
          }
          return outfields[index]
        })
        item.style.sources.osm.tiles[0] = queryParamsToUrl({
          url,
          params : {
            ...params,
            layerNames : newLayerNameArr.join(","),
            outfields : newOutfields.join(";")
          }
        })

      })
    })
    return isChange
  }

  const getLayerFilterOutFields = ({item, name, metaLayer}) => {
    const layers = item.style.layers.filter(a => a['source-layer'] == name)
    const outFileds = new Set()
    layers.map(layer => {
      const parseField = VectorUtils.filterFieldsHandle({
        layerItem : layer,
        outfields : null,
        layerFields : []
      })
      if((parseField && parseField.sqlObj && parseField.sqlObj.length > 0)) {
        parseField.sqlObj.filter(item => {
          return metaLayer.fields.find(field => field.name == item.label)
        }).map(item => outFileds.add(item.label))
      }
      extractBraceContentsRegex(layer?.layout?.['text-field'])?.filter(fieldName => {
        return (metaLayer.fields.find(item => item.name == fieldName))
      })?.map(item => {
        outFileds.add(item)
      })
    })
    return Array.from(outFileds).join(",")
  }

  const getDataIsFilterField = ({
    schemes,
    vectorData
  }) => {
    for(let i = 0 ; i < schemes.length ; i++) {
      const scheme = schemes[i]
      const data = vectorData.data[`${scheme.schemename}-${scheme.id}`]
      if(Array.isArray(data)) {
        const hasFilter = data.find(({style}) => style.layers.find(layer => !!layer.filter))
        if(hasFilter) {
          return true
        }
      }
    }
    return false
  }

  const getMetaData = async ({mapServerName}) => {
    const data = await getAllMetaData({mapServerName})
    return Array.isArray(data) ? data : null
  }

  const updateVectorFileds = ({metaData , schemes, vectorData}) => {
    let isUpdateFile = false 
    schemes.map(scheme => {
      const data = vectorData.data[`${scheme.schemename}-${scheme.id}`]
      if(!data) return
      data.map(({style}) => {
        const setFilterCollection = new Map()
        const setLayerCollection = new Set()
        const {params} = parseUrlQueryParams({
          url : style.sources.osm.tiles[0]
        })
        style.layers.map(layer => {
          let isHandle = true
          const metaLayer = metaData.find(item => item.name == layer['source-layer'])
          if(!metaLayer) {
            if( params.layerNames.indexOf(layer['source-layer']) > -1) {
              setLayerCollection.add(layer['source-layer'])
              return
            } else {
              isHandle = false
            }
          }
          isHandle && handleFilterField({
            layer,
            setFilterCollection,
            metaLayer
          })
          isHandle && handleLayoutTextField({
            layer,
            setFilterCollection,
            metaLayer
          })
        })
        if(updateStyleLayer({
          style,
          setLayerCollection
        })) {
          isUpdateFile = true
        }
        if(updateTileUrlAndField({
          style,
          setFilterCollection
        })) {
          isUpdateFile = true
        }
      })
      updateStyle(data)
    })
    return isUpdateFile
  }

  const handleFilterField = ({
    layer,
    setFilterCollection,
    metaLayer
  }) => {
    if(!layer.filter) return 
    const parseField = VectorUtils.filterFieldsHandle({
      layerItem : layer,
      outfields : null,
      layerFields : []
    })
    if(!(parseField && parseField.sqlObj && parseField.sqlObj.length > 0)) return
    const hasCondition = parseField.sqlObj.every(item => {
      return !item.label || metaLayer.fields.find(field => field.name == item.label)
    })
    if(!hasCondition) {
        const layerName = layer['source-layer']
        layer.filter = ""
        if(!setFilterCollection.has(layerName)) {
          setFilterCollection.set(layerName, new Set())
        }
        const setCollection = setFilterCollection.get(layerName)
        parseField.sqlObj.map(item => setCollection.add(item.label))
    }
  }

  const extractBraceContentsRegex = str => {
    const regex = /\{([^}]+)\}/g;
    const contents = [];
    let match;
    while ((match = regex.exec(str))!== null) {
        contents.push(match[1]);
    }
    return contents;
  }

  const handleLayoutTextField = ({
    layer,
    setFilterCollection,
    metaLayer
  }) => {
    const data = extractBraceContentsRegex(layer?.layout?.['text-field'])?.filter(fieldName => {
      return !(metaLayer.fields.find(item => item.name == fieldName))
    })
    if(data && data.length > 0) {
      layer['layout']['text-field'] = ""
      const layerName = layer['source-layer']
      if(!setFilterCollection.has(layerName)) {
        setFilterCollection.set(layerName, new Set())
      }
      const setCollection = setFilterCollection.get(layerName)
      data.map(item => {
        setCollection.add(item)
      })
    }
  }
  
  const updateTileUrlAndField = ({
    style,
    setFilterCollection
  }) => {
    const tileUrl = style?.sources?.osm?.tiles[0]
    if(!tileUrl || setFilterCollection.size < 1) return false
    const {params , url} = parseUrlQueryParams({
      url : tileUrl
    })
    const layerNameArr = params.layerNames.split(",")
    const outfields = params.outfields.split(";")
    if(layerNameArr.length != outfields.length ) return
    layerNameArr.map((layerName, index) => {
      if(!outfields[index]) return
      const layerNameCollection = setFilterCollection.get(layerName)
      if(!layerNameCollection) return
      const outFieldsArr = outfields[index].split(",")
      Array.from(layerNameCollection).map(field => {
        const indexCollections = []
        outFieldsArr.map((outFiled, index) => {
          if(outFiled == field) {
            indexCollections.push(index)
          }
        })
        indexCollections.sort((a,b) => a - b > 0 ? -1 : 1)
        indexCollections.map(index => {
          outFieldsArr.splice(index, 1)
        })
      })
      outfields[index] = outFieldsArr.join(",")
    })
    style.sources.osm.tiles[0] = queryParamsToUrl({
      url,
      params : {
        ...params,
        outfields : outfields.join(";")
      }
    })
    return true
  }

  const updateStyleLayer = ({
    style,
    setLayerCollection
  }) => {
    if(setLayerCollection.size == 0) {
      return false
    }
    let indexCollections = [] 
    style.layers.map((layer , index) => {
      const layerName = layer['source-layer']
      if(setLayerCollection.has(layerName)) {
        indexCollections.push(index)
      }
    })
    indexCollections.sort((a,b) => a - b > 0 ? -1 : 1)
    indexCollections.map(index => {
      style.layers.splice(index , 1)
    })
    const tileUrl = style?.sources?.osm?.tiles[0]
    const {params , url} = parseUrlQueryParams({
      url : tileUrl
    })
    const layerNameArr = params.layerNames.split(",")
    const outfields = params.outfields.split(";")
    indexCollections = []
    layerNameArr.map((layerName, index) => {
      if(setLayerCollection.has(layerName)) {
        indexCollections.push(index)
      }
    })
    indexCollections.sort((a,b) => a - b > 0 ? -1 : 1)
    indexCollections.map(index => {
      layerNameArr.splice(index , 1)
      outfields.splice(index , 1)
    })
    style.sources.osm.tiles[0] = queryParamsToUrl({
      url,
      params : {
        ...params,
        outfields : outfields.join(";"),
        layerNames :  layerNameArr.join(";"),
      }
    })
    return true
  }

  const updateStyle = (data) => {
    const indexCollections = []
    data.map((item , index) => {
      if(!(item.style && item.style.layers && item.style.layers.length > 0)) {
        indexCollections.push(index)
      }
    })
    indexCollections.sort((a,b) => a - b > 0 ? -1 : 1)
    indexCollections.map(index => {
      data.splice(index, 1)
    })
  }

  const previewMetaData = record => {
    setCurrentMetaData(record);
    setPreviewVisible(true);
  };

  const metadata = record => {
    setCurrentMetaData(record);
    setMeteDataVisible(true);
  };

  const solutionName = () => {
    getSolutionList({
      _version: 9999,
    }).then(res => {
      setSolutionNames(res.data.currentSolution);
    });
  };
  const onSubmit = prop => {
    setVisible(false);
    setFlag(flag + 1);
    setAddVisible(false);
  };
  const delConfirm = record => {
    console.log(' record.ServiceName', record.ServiceName.split('.'));
    let query = {
      serviceName: record.ServiceName.split('.')[0],
      _version: 9999,
      solution: solutionNames,
    };
    deleteVectorService(query).then(res => {
      if (res.success) {
        setFlag(flag + 1);
        //deleteVectorData(record)
        notification.success({
          message: '提示',
          duration: 3,
          description: '删除元数据成功',
        });
      } else {
        notification.error({
          message: '提示',
          duration: 3,
          description: '删除元数据失败',
        });
      }
    });
  };

  const deleteVectorData = async (record) => {
    try {
      const mapServerName = record?.ServiceName?.split('.')?.[0]
      if(!mapServerName) return
      const schemes = await updateCurrentMapschemes({mapServerName})
      if(schemes.length == 0) return
      const vectorData = await getVectorConfigData({
        schemes,
        mapServerName
      })
      if(!vectorData) return 
      schemes.map(scheme => {
        delete vectorData.data[`${scheme.schemename}-${scheme.id}`]
      })
      await AddStyleConfigJson({
        fileName : "StyleConfig",
        preventCache : Date.now()
      }, vectorData)
    } catch {

    }
  }

  const delConfirmSliced = record => {
    const { servicename = '' } = record;
    setTreeLoading(true);
    deleteConfig({
      servicename,
      terminalType: 'base',
      isBaseMap: true,
    })
      .then(res => {
        setFlag(flag + 1);
        if (res.code == '0') {
          // form.resetFields();
          // callBackSubmit();
          notification.success({
            message: '提示',
            duration: 3,
            description: res.message || '删除成功',
          });
        } else {
          notification.error({
            message: '提示',
            duration: 3,
            description: res.message || '删除失败',
          });
        }
      })
      .catch(err => {
        setFlag(flag + 1);
        setTreeLoading(false);
      });
  };
  const handleAdd = () => {
    setType('add');
    if (radioType == 1) {
      setVisible(true);
    } else {
      setAddVisible(true);
    }
  };
  useEffect(() => {
    renderTile({ info: searchValue });
    renderTileSliced();
  }, [flag]);
  // 获取瓦片数据配置数据
  const renderTile = (params = { info: '' }) => {
    setTreeLoading(true);
    solutionName();
    GetVectorService(params)
      .then(res => {
        setTreeLoading(false);
        if (res.msg === 'Ok') {
          let arr = [];
          res.data.VectorList.map(item => {
            arr.push(false);
          });
          setLoading(arr);

          setTileData(res.data.VectorList);
        } else {
          notification.error({
            message: '获取失败',
            description: res.message,
          });
        }
      })
      .catch(err => {
        if (err.message.indexOf('timeout') !== -1) {
          notification.error({
            message: '提示',
            duration: 3,
            description: '请求超时',
          });
        } else {
          notification.error({
            message: '提示',
            duration: 3,
            description: err.message,
          });
        }
        setTreeLoading(false);
      });
  };

  const renderTileSliced = () => {
    setTreeTileLoading(true);
    GettMaplayer({
      terminalType: 'base',
      isBaseMap: true,
    })
      .then(res => {
        setTreeTileLoading(false);
        if (res.code == '0') {
          let newdata = res.data.general.baseMap.layers?.filter(i => i.isVector === 1);
          setTileSlicedData(newdata);
          let data = [];
          newdata.map(item => {
            data.push(item.servicename);
          });
          setName(data);
        } else {
          notification.error({
            message: '获取失败',
            description: res.message,
          });
        }
      })
      .catch(err => {
        setTreeTileLoading(false);
        if (err.message.indexOf('timeout') !== -1) {
          notification.error({
            message: '提示',
            duration: 3,
            description: '请求超时',
          });
        } else {
          notification.error({
            message: '提示',
            duration: 3,
            description: err.message,
          });
        }
      });
  };
  // 搜索
  const handleSearch = text => {
    setFlag(flag + 1);
  };
  // 搜索框改变时存储输入的值
  const handleChange = e => {
    setSearchValue(e.target.value);
  };

  const updateAll = async () => {
    let query = {
      version: 9999,
      solution: solutionNames,
    };
    for (const [index, item] of tileData.entries()) {
      setAllLoading(true);
      query.serviceName = item.ServiceName;
      let res = null;
      res = await updatePublishedMetaData(query);
      if (res.success) {
        setAllLoading(false);
        notification.success({
          message: '提示',
          duration: 1,
          // description: `${item.ServiceName}更新辣`,
          description: `更新元数据成功`,
        });
      } else {
        setAllLoading(false);
        notification.error({
          message: '提示',
          duration: 3,
          description: '更新元数据失败',
        });
      }
      if (index === tileData.length - 1) {
        setFlag(flag + 1);
      }
    }
  };

  const handleSelect = e => {
    setRadioType(e.target.value);
  };

  const changebaseMap = e => {
    setType('edit');
    setRecord(e);
    setAddVisible(true);
  };

  return (
    <>
      <div className={styles.pipeNetwork}>
        <div className={styles.tileBtnVe}>
          <div className={styles.tileBtnLeft}>
            <span>管网类型:</span>
            <Radio.Group defaultValue="1" value={radioType} onChange={e => handleSelect(e)}>
              <Radio.Button value="1" style={{ width: '90px', textAlign: 'center' }}>
                管网
              </Radio.Button>
              <Radio.Button value="2" style={{ width: '90px', textAlign: 'center' }}>
                切片管网
              </Radio.Button>
            </Radio.Group>
          </div>
          <div className={styles.tileBtnRight}>
            {radioType == 1 && (
              <>
                <span style={{ marginLeft: '20px', marginRight: '5px' }}>快速检索</span>
                <Search
                  allowClear
                  placeholder="请输入服务名或工程名"
                  onSearch={handleSearch}
                  onChange={handleChange}
                  value={searchValue}
                  enterButton
                  style={{ width: '300px', marginRight: '20px' }}
                />
                <Button
                  type="primary"
                  onClick={() => {
                    updateAll();
                  }}
                  loading={allLoading}
                  style={{ marginRight: '20px' }}
                >
                  批量更新
                </Button>
              </>
            )}
            <Button
              type="primary"
              onClick={() => {
                handleAdd();
              }}
            >
              新增
            </Button>
          </div>
        </div>
        <div style={{ height: 'calc(100% - 51px)', width: '100%' }}>
          <Table
            loading={radioType == 1 ? treeLoading : treeTileLoading}
            columns={radioType == 1 ? columns : columnsPart}
            dataSource={radioType == 1 ? tileData : tileSlicedData}
            bordered
            rowKey="CreateTime"
            scroll={{ y: 'calc(100% - 70px)' }}
            pagination={{
              showTotal: (total, range) => `第${range[0]}-${range[1]} 条/共 ${total} 条`,
            }}
          />
        </div>
        <AddModal
          visible={visible}
          onCancel={() => setVisible(false)}
          callBackSubmit={onSubmit}
          type={type}
          formObj={formObj}
          solutionNames={solutionNames}
        />
        <PreviewModal
          visible={previewVisible}
          onCancel={() => setPreviewVisible(false)}
          metaData={currentMetaData}
        />
        <MeteDataModal
          visible={meteDataVisible}
          onCancel={() => setMeteDataVisible(false)}
          metaData={currentMetaData}
        />
        <AddSlicedModal
          visible={addVisible}
          onCancel={() => setAddVisible(false)}
          callBackSubmit={onSubmit}
          type={type}
          formObj={record}
          name={name}
        />
      </div>
    </>
  );
};
export default VectorData;