import {ProCard, ProTable} from '@ant-design/pro-components';
import {Button, message} from 'antd';
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {TreeMenu} from '../../components/TreeMenu.jsx';
import {DIM_TYPE_ENUM, ProTableDefault, STATUS_TYPE, TYPE_ENUM} from '../../constants.js';
import {columnsFactory} from '../../../utils/columnsFactory.jsx';
import {DomainForm} from './components/DomainForm.jsx';
import {SelectModal} from '../../components/SelectModal';
import {ModalDesign} from "./components/ModalDesign.jsx";
import {MODAL_TYPE} from "./constants.js";
import {useAppDispatch, useAppSelector} from "../../../redux/configureStore";
import {
  createDomain,
  createModal,
  updateModal,
  deleteModal,
  getDBSource,
  getDomains,
  getModalDetail,
  getModals,
  roleAuthGrant,
  getAuthList,
  roleAuthDelete,
  updateDomain,
  removeDomain, getDimensions
} from "../MainPage/slice/thunks";
import {selectDomains, selectModals} from "../MainPage/slice/selectors";
import {useWorkFlow} from "../../hooks/useWorkFlow";
import {CALC_TYPE, CALC_TYPE_REVERS} from "../IndexDefine/constants";
import {ActionIcon} from "../../components/ActionIcon";
import {AuthorizationPanel} from "../IndexDefine/components/AuthorizationPanel";
import useI18NPrefix from "../../hooks/useI18NPrefix";


export const ModalManage = () => {
  const t = useI18NPrefix('global');
  const modalTypeOption = [
    {label: t("title.quickStart"), value: MODAL_TYPE.QUICK, icon: true},
    {label: t("title.SQLStart"), value: MODAL_TYPE.SQL, icon: true},
  ]
  const baseColumns = [
    {
      title: t("columns.bizName"),
      dataIndex: 'bizName',
    },
    {
      title: t("columns.model")+t("columns.name"),
      dataIndex: 'name',
    },
    {
      title: t("columns.alias"),
      dataIndex: 'alias',
    },
    {
      title: t("columns.description"),
      dataIndex: 'description',
    },
    {
      title: t("columns.datasource"),
      dataIndex: 'datasourceName',
    },
    {
      title: t("columns.establishingMode"),
      dataIndex: 'createMethod',
      valueType: 'select',
      fieldProps: {
        options: modalTypeOption
      },
    },
    {
      title: t("columns.status"),
      dataIndex: 'status',
      valueType: 'select',
      valueEnum: STATUS_TYPE,
    },
    {
      title: t("title.atomicNum"),
      dataIndex: 'ATOMIC',
    },
    {
      title: t("title.derivedNum"),
      dataIndex: 'DERIVED',
    },
    {
      title: t("title.compositeNum"),
      dataIndex: 'COMPOSITE',
    }
  ]
  const { clear } = useWorkFlow();
  const dispatch = useAppDispatch();
  const domains = useAppSelector(selectDomains);
  const modals = useAppSelector(selectModals);
  /** 格式化表头 */
  const [columns, setColumns] = useState([]);

  /** 打开主题域表单 */
  const [domainModalOpen, setDomainModalOpen] = useState(false);
  /** 模型设计面板 */
  const [openModalDesign, setDesignModalOpen] = useState(false);
  /** 授权面板 */
  const [openAuth,setOpenAuth] = useState(false);

  /** 打开模型弹窗*/
  const onDomainModalOpen = useCallback(
    ()=> setDomainModalOpen(false)
    ,[]
  );

  /** Table action 的引用，便于自定义触发 */
  const actionRef = useRef();

  /** 数据缓存*/
  const commonRef = useRef({
    domainSelect: {
      id:0,
      name:'模型信息'
    },
    modalSelect: {
      value:null,
      label:null,
    },
  });

  /** 关闭模型弹窗*/
  const onModalDesignClose = useCallback(
    ()=>{
      clear();
      commonRef.current.modelDetail=null;
      setDesignModalOpen(false);
    },[]
  )

  useEffect(() => {
    /** 获取主题域 */
    dispatch(getDomains());

    setColumns(
      columnsFactory({
        dataSource: baseColumns,
        onDelete:({id},reload)=> {
          dispatch(deleteModal({
            id,
            resolve(){
              reload()
            }
          }))
        },
        onDetail:onModalDetail,
      })
    )
  }, [])

  /** 模型编辑 */
  const onModalDetail=useCallback(({id})=>{
    // 获取维度
    dispatch(getDimensions({id}));
    // 获取数据源
    dispatch(getDBSource());
    // 获取模型明细
    dispatch(getModalDetail({
      id,
      resolve(data){
        commonRef.current.modelDetail=data
        commonRef.current.modalSelect=modalTypeOption.find(item=>item.value === data.modelDetail.queryType);
        setDesignModalOpen(true);
      }
    }))
  },[])

  /** 选择创建模式 */
  const onModelSelect = useCallback((info) => {
    // 主题不能为空
    if (commonRef.current.domainSelect.id){
      // 获取数据源
      dispatch(getDBSource());
      setDesignModalOpen(true);
      commonRef.current.modalSelect=info;
    }else {
      message.error(t("validation.domain"))
    }
  }, [modalTypeOption]);

  /** 侧边栏主题域钩子 */
  const onSelect = (keys, info) => {
    const {node} = info;
    if (commonRef.current.domainSelect?.id!==node?.data?.id){
      dispatch(getModals({domainId:node?.data?.id}));
      commonRef.current.domainSelect=node?.data;
    }
  };

  /** 侧边栏主题域钩子 */
  const onRightClick = ({event})=>{
    event.preventDefault();
  }

  /** 主题域过滤 */
  const onSearch = (keys) => {
    console.log('onSearch', keys);
  };

  /** 主题域表单提交 */
  const domainFormSubmit = useCallback((values) => {
    const {parentId,id} = values;
    const params = {
      ...values,
      parentId: parentId ? parentId : 0
    }
    if (id){
      dispatch(
        updateDomain({
          params,
          resolve(){
            message.success(t("validation.success"));
            dispatch(getDomains());
            setDomainModalOpen(false)
          }
        })
      );

    }else {
      dispatch(
        createDomain({
          params,
          resolve(){
            message.success(t("validation.success"));
            dispatch(getDomains());
            setDomainModalOpen(false)
          }
        })
      );
    }

  },[]);

  /** 模型设计提交 */
  const onDesignFormFinish=useCallback((values)=>{
    const {modalSelect,domainSelect,modelDetail} = commonRef.current;
    if (!values?.domainId && domainSelect.id<=0){
      message.warning(t("validation.domain"))
      return false
    }
    const {modelType,classify,nodes,edges,tableName,bizName,name,description,dbSource,db,sqlStr} = values;

    // 多表之间的关联关系(仅快速创建模式使用)
    let joinRelations = [];
    let sqlRelation = ` FROM ${tableName} `;
    if (MODAL_TYPE.QUICK===modelType){
      // 快速创建-多表
      if (edges.length>0){
        for (const e in edges) {
          const edge = edges[e];
          const left = nodes.find(n=>`${n.tableName}.${n.fieldName}`===edge.source);
          const right = nodes.find(n=>`${n.tableName}.${n.fieldName}`===edge.target);
          const leftTable = left.tableName;
          const leftFields = left.fieldName;
          const rightTable = right.tableName;
          const rightFields = right.fieldName;
          // SQL连接关系拼接
          sqlRelation = sqlRelation + ` LEFT JOIN ${rightTable} ON ${edge.source}=${edge.target}`;
          joinRelations.push({
            left:leftTable,
            leftFields:[leftFields],
            right:rightTable,
            rightFields:[rightFields],
            type:'LeftJoin',
            conditions:[
              {
                left:leftFields,
                right:rightFields,
                operator: "IN",
              }
            ]
          });
        }
      }
    }

    if (MODAL_TYPE.SQL===modelType){
      const regex = /from/i;
      const match = sqlStr.match(regex);
      if (match) {
        const fromIndex = match.index;
        sqlRelation = sqlStr.slice(fromIndex);
      }
    }


    // 主键
    let identifiers = [];
    let dimensions = [];
    let measures = [];
    for (const c in classify) {
      const {data,value} = classify[c];
      if (value==="isKey"){
        identifiers = data
          .filter(item=>item.tableName!=='自定义')
          .map(item=>({
            name: item.fieldName,
            type: DIM_TYPE_ENUM.IDENTIFY,
            bizName: `${bizName}_${item.bizName}`,
            isCreateDimension: 1
          }))
      }
      if (value==="datetime"){
        for (const i in data) {
          const item = data[i];
          if (item.tableName==='自定义') continue
          dimensions.push({
            name: item.fieldName,
            type: DIM_TYPE_ENUM.DATETIME,
            bizName: `${bizName}_${item.bizName}`,
            isCreateDimension: 1,
            description: item.comment,
            typeParams: {
              isPrimary: true,
              timeGranularity: 'day'
            }
          })
        }
      }
      if (value==="common"){
        for (const i in data) {
          const item = data[i];
          if (item.tableName==='自定义') continue
          dimensions.push({
            name: item.fieldName,
            type: DIM_TYPE_ENUM.CATEGORICAL,
            bizName: `${bizName}_${item.bizName}`,
            isCreateDimension: 1,
            description: item.comment
          })
        }
      }
      if (value==="measure"){
        measures = data.map(item=>({
          name: item.fieldName,
          agg: CALC_TYPE_REVERS[CALC_TYPE.SUM],
          expr: item.bizName,
          bizName: `${bizName}_${item.bizName}`,
          isCreateDimension: 1,
          alias: item.comment,
          constraint: ""
        }))
      }
    }
    // SQL字段拼接
    let sqlString = "SELECT "
    nodes.forEach((value,index)=>{
      if (index!==nodes.length-1){
        if (joinRelations.length>0){
          sqlString = `${sqlString} ${value.tableName}.${value.fieldName},`
        }else {
          sqlString = `${sqlString} ${value.tableName}.${value.fieldName} AS ${bizName}_${value.bizName},`
        }

      }else {
        if (joinRelations.length>0){
          sqlString = `${sqlString} ${value.tableName}.${value.fieldName} `
        }else {
          sqlString = `${sqlString} ${value.tableName}.${value.fieldName} AS ${bizName}_${value.bizName} `
        }

      }
    })

    const sqlQuery = MODAL_TYPE.SQL===modelType ? sqlStr : (joinRelations.length>0 ? sqlString+sqlRelation : "")
    const modalParams = {
      id:modelDetail?.id,
      databaseId: dbSource,
      dbName:db,
      domainId:values?.domainId || domainSelect.id,
      alias: name,
      sourceType: modalSelect.label,
      name:name,
      bizName: bizName,
      description: description,
      typeEnum: TYPE_ENUM.MODEL,
      sensitiveLevel: 0,
      modelDetail: {
        sqlQuery,
        queryType: modalSelect.value,
        tableQuery: edges?.length===0 ? tableName :null,
        joinRelations: joinRelations,
        identifiers: identifiers,
        dimensions: dimensions,
        measures: measures,
        fields:nodes
          .filter(item=>item.tableName!=='自定义')
          .map(value=>({
            tableName:value.tableName,
            fieldName:value.fieldName,
            dataType:value.dataType,
            comment:value.comment,
            bizName:`${bizName}_${value.bizName}`
          }))
      }
    }

    if (modelDetail?.id){
      dispatch(updateModal({
        params:modalParams,
        resolve() {
          message.success(t("validation.success"))
          clear()
          actionRef.current?.reload()
          commonRef.current.modelDetail=null;
          setDesignModalOpen(false);
        }
      }))
    }else {
      dispatch(createModal({
        params:modalParams,
        resolve() {
          message.success(t("validation.success"))
          clear()
          actionRef.current?.reload();
          commonRef.current.modelDetail=null;
          setDesignModalOpen(false);
        }
      }))
    }
  },[])

  /** 右键情景框选择后回调 */
  const onRightSelect = (event)=>{
    if (event.key==='update'){
      setDomainModalOpen(true)
    }
    if (event.key==='auth'){
      setOpenAuth(true)
    }
    if (event.key==='remove'){
      dispatch(
        removeDomain({
          id:commonRef.current.domainSelect.id,
          resolve(){
            message.success(t("validation.success"));
            dispatch(getDomains());
          }
        })
      )
    }
  }

  /** 左侧主题树目录 */
  const buildTree = useMemo(()=>{
    const items = [
      {
        key: 'update',
        label: t("operation.update")
      },
      {
        key: 'auth',
        label: t("operation.auth")
      },
      {
        key: 'remove',
        label: t("operation.remove")
      }
    ];
    function insertKey(arr) {
      let temp = [];
      for (const i in arr) {
        const record = arr[i];
        const {children} = record;
        let item = {
          key: record.id,
          title:<ActionIcon trigger="contextMenu" items={items} children={record.title} onSelect={onRightSelect} tooltip={t("placeholder.rightClick")}/>,
          data: record,
          isLeaf: children?.length===0,
        }
        if (children?.length>0) {
          item.children = insertKey(children)
        }
        temp.push(item)
      }
      return temp
    }
    return insertKey(domains)
  },[domains]);

  /** 关闭授权面板 */
  const onAuthPanelClose = useCallback(()=>{
    setOpenAuth(false)
  },[])

  /** 获取主题域 */
  const onGetAuthList = ()=>{
    dispatch(getAuthList({
      params:{
        dataType:TYPE_ENUM.DOMAIN
      }
    }))
  }

  /** 主题域授权 */
  const onDomainAuthFinish=useCallback((value)=>{
    dispatch(roleAuthGrant({
      params:value,
      resolve(){
        onGetAuthList()
      }
    }))
  },[])

  /** 删除授权 */
  const onAuthDelete = useCallback((row)=>{
    dispatch(roleAuthDelete({
      id:row.roleId,
      resolve(){
        onGetAuthList()
      }
    }))
  },[])

  /** 创建主题域 */
  const onCreateDomain = useCallback(()=>{
    commonRef.current.domainSelect={}
    setDomainModalOpen(true)
  },[])

  return (
    <>
      {/** 主题域编辑面板 */}
      <DomainForm
        open={domainModalOpen}
        onCancel={onDomainModalOpen}
        onFinish={domainFormSubmit}
        values={commonRef.current.domainSelect}
      />
      {/** 主题域授权面板 */}
      <AuthorizationPanel
        type={TYPE_ENUM.DOMAIN}
        open={openAuth}
        onCancel={onAuthPanelClose}
        onFinish={onDomainAuthFinish}
        values={commonRef.current.domainSelect}
        onDelete={onAuthDelete}
      />
      {/** 模型设计面板 */}
      <ModalDesign
        open={openModalDesign}
        onCancel={onModalDesignClose}
        type={commonRef.current.modalSelect}
        initialValues={commonRef.current?.modelDetail}
        onFinish={onDesignFormFinish}
      />
      {/** 模型列表 */}
      <ProCard gutter={8} ghost>
        <ProCard
          bordered
          title="主题"
          colSpan="20%"
          headerBordered
          style={{height: '85vh'}}
          extra={
            <Button type="link" size="large" onClick={onCreateDomain}>+{t("button.domainCreate")}</Button>
          }
        >
          <TreeMenu
            treeData={buildTree}
            onSelect={onSelect}
            onSearch={onSearch}
            onRightClick={onRightClick}
          />
        </ProCard>
        <ProCard bordered={false} bodyStyle={{padding: 0}} style={{backgroundColor:'inherit',height: '85vh'}}>
          <ProTable
            {...ProTableDefault}
            actionRef={actionRef}
            headerTitle={commonRef.current.domainSelect.name}
            columns={columns}
            dataSource={modals}
            pagination={{
              pageSize: 20,
              onChange: (page) => console.log(page),
            }}
            request={async ()=>{
              if (commonRef.current.domainSelect.id){
                await dispatch(getModals({domainId:commonRef.current.domainSelect.id}))
              }
            }}
            toolBarRender={() => [
              <SelectModal
                description={t("placeholder.establishingMode")}
                title={t("title.establishingMode")}
                options={modalTypeOption}
                onSelect={onModelSelect}
              />
            ]}
          />
        </ProCard>
      </ProCard>
    </>
  );
};
