import {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {Button, Descriptions, Divider, Drawer, Table, Tag, DatePicker, message, Spin, Modal} from "antd";
import {styled} from "styled-components";
import {UpOutlined} from "@ant-design/icons";
import moment from "moment";
import {ProCard} from "@ant-design/pro-components";
import {PureTableCard} from "../../../components/PureTableCard";
import {FilterPanel} from "../../../components/FilterPanel";
import {WorkFlowPanel} from "../../../components/WorkFlow";
import {useAppDispatch} from "../../../../redux/configureStore";
import {CopyToClipboard} from 'react-copy-to-clipboard';
import {
  getMetricLineage,
  getMetricSQL,
  metricVersion,
  queryMetric,
  queryTask,
  queryTaskLog,
  runTask
} from "../../MainPage/slice/thunks";
import {
  CALC_TYPE, DATA_TYPE,
  SEN_COLOR_LEVEL,
  SENSITIVE,
  STATUS_COLOR_LEVEL,
  TASK_STATUS
} from "../constants";
import {useWorkFlow} from "../../../hooks/useWorkFlow";
import {MetricNode} from "../../../components/WorkFlow/atomic/MetricNode";
import {DIM_TYPE_ENUM, STATUS_TYPE} from "../../../constants";
import dayjs from 'dayjs';
import useI18NPrefix from "../../../hooks/useI18NPrefix";

const { RangePicker } = DatePicker;

const versionColumns = [
  {
    title: '版本号',
    dataIndex: 'versionNo',
    key: 'versionNo'
  },
  {
    title: '内部版本号',
    dataIndex: 'version',
    key: 'version'
  },
  {
    title: '创建日期',
    dataIndex: 'createdAt',
    key: 'createdAt',
    render: (text) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
  },
  {
    title: '创建状态',
    dataIndex: 'status',
    key: 'status',
    render: (text) => <Tag color={text?"success":"volcano"}>{text?'已过期':'使用中'}</Tag>,
  },

];


export const IndexDetail = memo(({
 admin,
 open,
 title,
 onClose,
 values,
 onCopy,
 persistence
}) => {
  const t = useI18NPrefix('global');
  const isNULL = t("title.null");
  const {clear,updateNodesState,updateEdgesState,getNodesState,getEdgesState} = useWorkFlow();
  const dispatch = useAppDispatch();
  const [otherOpen, setOtherOpen] = useState(true);
  const [tab, setTab] = useState('tab1');
  const [queryData,setQueryData] = useState({});
  const [loading, setLoading] = useState(false);
  const [invokeData,setInvokeData] = useState([]);
  const [version,setVersion] = useState([]);
  const invokeRangeRef = useRef({});
  const [openLog,setOpenLog] = useState(false);
  const logRef = useRef(null);
  const cacheSQL = useRef(null);
  const vokeConfig = persistence?.defaultConfig && JSON.parse(persistence?.defaultConfig);
  const rangePresets = [
    {
      label: t("operation.last")+" 7 "+t("operation.day"),
      value: [dayjs().add(-7, 'd'), dayjs()],
    },
    {
      label: t("operation.last")+" 14 "+t("operation.day"),
      value: [dayjs().add(-14, 'd'), dayjs()],
    },
    {
      label: t("operation.last")+" 30 "+t("operation.day"),
      value: [dayjs().add(-30, 'd'), dayjs()],
    },
    {
      label: t("operation.last")+" 90 "+t("operation.day"),
      value: [dayjs().add(-90, 'd'), dayjs()],
    },
  ];
  const columns = [
    {
      title: t("columns.processInstanceName"),
      dataIndex: 'processInstanceName',
      key: 'processInstanceName'
    },
    {
      title: t("columns.taskCode"),
      dataIndex: 'taskCode',
      key: 'taskCode',
    },
    {
      title: t("columns.taskDefinitionVersion"),
      dataIndex: 'taskDefinitionVersion',
      key: 'taskDefinitionVersion',
    },
    {
      title: t("columns.invokeStartTime"),
      dataIndex: 'startTime',
      key: 'startTime',
      render: (text) => text && dayjs(text).format('YYYY-MM-DD HH:mm:ss'),
    },
    {
      title: t("columns.invokeEndTime"),
      dataIndex: 'endTime',
      key: 'endTime',
      render: (text) => text && dayjs(text).format('YYYY-MM-DD HH:mm:ss'),
    },
    {
      title: t("columns.state"),
      dataIndex: 'state',
      key: 'state',
      render: (text) => <Tag color={TASK_STATUS[text]?.color}>{TASK_STATUS[text]?.label}</Tag>
    },
    {
      title: t("columns.option"),
      key: 'option',
      dataIndex: 'option',
      render: (_, {state,id}) => (
        (state === "SUBMITTED_SUCCESS" || state === "RUNNING_EXECUTION")
          ? <Spin/> : <a onClick={()=>onHandelInvokeLog(values.id,id)}>{t("button.detail")}</a>
      ),
    },
  ];

  useEffect(()=>{
    if (!open){
      setInvokeData([])
      setQueryData([])
    }
  },[open])

  useEffect(() => {
    const findList = invokeData.filter(item=>
      item.state==='SUBMITTED_SUCCESS' ||
      item.state==='RUNNING_EXECUTION'
    )

    if (findList.length>0){
      const interval = setInterval(() => {
        onQueryTask()
      }, 5000);
      return () => clearInterval(interval);
    }
  }, [invokeData]);

  const formatNodes = (data,position)=>{
    const {children} = data;
    let initNodes = [];
    let initEdges = [];
    initNodes.push({
      id: `${data.metricId}`,
      type:'metric',
      data: {
        label:data.metricName,
        width:data.metricName.length * 25,
      },
      position
    })
    if (children) {
      children.forEach((item,index)=>{
        const newPosition = {
          x:position.x + data.metricName.length * 35,
          y:(position.y*0.5)+index*90,
        }
        initEdges.push({
          id: `${data.metricId}-${item.metricId}`,
          style: {strokeWidth: 1, stroke: 'black'},
          source: `${data.metricId}`,
          target: `${item.metricId}`
        })
        const {nodes,edges} = formatNodes(item,newPosition);
        initNodes = [...initNodes,...nodes]
        initEdges = [...initEdges,...edges]
      })
    }
    return {
      nodes:initNodes,
      edges:initEdges
    }
  }

  // 查询调度记录
  const onQueryTask=(info)=>{
    let params;
    if (info){
      params = info
    }else{
      params={
        id:values?.id,
        ...invokeRangeRef.current
      }
    }

    dispatch(queryTask({
      params,
      resolve(data) {
        setInvokeData((data||[]).filter(item=>item.processInstanceName))
      }
    }))
  }

  useEffect(() => {
    if (open && values.id){
      dispatch(getMetricLineage({
        id:values.id,
        resolve(data) {
          const {nodes,edges} = formatNodes(data,{x: 100, y: 100})
          updateNodesState(nodes)
          updateEdgesState(edges)
        }
      }))

      if (values?.isPublish){
        onQueryTask({id:values.id})
      }

      dispatch(metricVersion({
        id:values.id,
        resolve(data){
          setVersion(data)
        }
      }))

      handleMetricSQL()
    }
    return () => {
      clear()
    };
  }, [open,values]);


  /** 筛选条件更改时的回调处理*/
  const onLogicChange = async ({days, dimension, tags}) => {
    setLoading(true)
    const {id, domainId} = values;
    const groups = (dimension||[]).filter(item=>item.semanticType!=='DATE').map(item=>item.bizName);
    let dateInfo = {
      dateMode: "BETWEEN",
      startDate: moment().subtract(days ? days : 0, 'days').format('YYYY-MM-DD'),
      endDate: moment().format('YYYY-MM-DD'),
      dateList: [],
      unit: 1,
      period: "day",
      detectWord: "",
      isInherited: false,
      groupByDate: groups.length<dimension?.length
    }
    let filters = [];
    (tags||[]).forEach(tag=>{
      const dimensionObj = JSON.parse(tag.dimension);
      if (dimensionObj.semanticType!=="DATE"){
        filters.push({
          id: tag.value,
          relation: "FILTER",
          bizName: dimensionObj.bizName,
          name: tag.bizName,
          operator: tag.condition,
          value: tag.keyword,
          semanticType: dimensionObj.semanticType,
          children: []
        })
      }else {
        dateInfo = {
          dateMode: "BETWEEN",
          startDate: tag.startDate,
          endDate: tag.endDate,
          dateList: [],
          unit: 0,
          period: 'day',
          detectWord: "",
          isInherited: false,
          groupByDate: true
        }
      }
    })
    const params = {
      domainId,
      limit: 1000,
      metricIds: [id],
      metricNames: [],
      dimensionIds: (dimension||[]).map(item=>item.value),
      dimensionNames: [],
      dateInfo: dateInfo,
      filters,
    }
    await dispatch(queryMetric({
      params,
      resolve(data) {
        setQueryData(data)
      }
    }))
    setLoading(false)
  };

  /** 指标概览模块 */
  const LogicPanel = useMemo(() =>
    <FilterPanel
      onChange={onLogicChange}
      delay={1000}
      options={{
        dimension:(values?.dimensions || [])
          // .filter(v=>v?.type!==DIM_TYPE_ENUM.DATETIME)
          .map(v=>({
            value:v.id,
            label:v.description||v.name,
            semanticType:v.semanticType,
            bizName:v.bizName
          }))
      }}
      loading={loading}
      dataSource={queryData}
      initCall={true}
      requires={["dimension"]}
    />
    , [loading,open,queryData]
  );

  /** 版本概览模块 */
  const VersionPanel = useMemo(() => (
    <Table columns={versionColumns} dataSource={version}/>
  ), [version]);

  /** 调度时间范围*/
  const onRangeChange = (dates, dateStrings) => {
    if (dates) {
      invokeRangeRef.current={
        startDate:dateStrings[0],
        endDate:dateStrings[1]
      }
    } else {
      invokeRangeRef.current=null
    }
  };

  /** 立即调度 */
  const onInvokeTask = ()=>{
    if (values?.id){
      dispatch(runTask({
        id:values?.id,
        resolve(data){
          if (data){
            message.success(t("validation.invokeSuccess"))
            setTimeout(()=>{
              onQueryTask()
            },1000)
          }else {
            message.error(t("validation.invokeFailure"))
          }
        }
      }))
    }
  }

  /** 获取指标的SQL字符串*/
  const handleMetricSQL = async ()=>{
    const {payload} = await dispatch(getMetricSQL(values?.id));
    cacheSQL.current = payload;
  }

  /** 调度记录模块 */
  const InvokePanel = useMemo(() => (
    <>
      <div style={{marginBottom:20}}>
        <span>{t("title.dateRanges")}：</span>
        <RangePicker presets={rangePresets} onChange={onRangeChange} />
        <Button type="primary" style={{marginLeft:15}} onClick={()=>onQueryTask()}>{t("button.query")}</Button>
        {admin && <Button style={{marginLeft: 15}} onClick={onInvokeTask}>{t("button.invoke")}</Button>}
        {admin &&
          <CopyToClipboard
            text={cacheSQL.current}
            onCopy={()=>{message.success('已复制到剪切板')}}
          >
            <Button style={{marginLeft: 15}}>复制SQL</Button>
          </CopyToClipboard>
        }
      </div>
      <Table
        columns={columns}
        dataSource={invokeData}
        pagination={{pageSize: 10}}
      />
    </>
  ), [values,invokeData]);

  /** 标签页切换*/
  const onTabChange = useCallback((tab)=>{
    setTab(tab)
  },[tab,values])

  /** 查看调用日志 */
  const onHandelInvokeLog =(metricId,instanceId)=>{
    dispatch(queryTaskLog({
      metricId,
      instanceId,
      resolve(data){
        logRef.current=data.message
        setOpenLog(true)
        console.log(data)
      }
    }))
  }

  /** 复制指标 */
  const onCopyMetric = () =>{
    const init = {
      ...values,
      id:null
    }
    onCopy({key:'update'},init)
  }

  return (
    <Drawer
      styles={{
        body: {
          padding: '10px 0 10px 30px'
        }
      }}
      width={1230}
      destroyOnClose
      maskClosable={false}
      title={title}
      placement="right"
      open={open}
      onClose={onClose}
    >
      {/** 头信息 及 操作按钮 */}
      <Wrapper>
        <Title>
          {values?.title}
          {values?.tag &&
            <Tag style={{marginLeft: 10}} color={values?.tag.color}>{values?.tag.label}</Tag>
          }
        </Title>
        <Extra>
          <Button type="primary" ghost style={{marginRight: 15}}>{t("button.baseInfoDetail")}</Button>
          <Button type="primary" ghost style={{marginRight: 15}}>{t("button.metricCreate")}</Button>
          <Button type="primary" ghost style={{marginRight: 15}} onClick={onCopyMetric}>{t("button.metricCopy")}</Button>
        </Extra>
      </Wrapper>
      <Divider style={{margin: '10px 0 10px 0'}}/>
      {/** 信息体 */}
      <Container>
        <Descriptions column={5}>
          <Descriptions.Item label={t("formItem.domain")}>{values.domainName}</Descriptions.Item>
          <Descriptions.Item label={t("formItem.metricCode")}>{values.bizName}</Descriptions.Item>
          <Descriptions.Item label={t("formItem.sensitiveLevel")} contentStyle={{color:SEN_COLOR_LEVEL[values.sensitiveLevel]}} children={SENSITIVE[values.sensitiveLevel]}/>
          <Descriptions.Item label={t("formItem.lastVersionNo")}>{values.lastVersionNo||"V20240629001"}</Descriptions.Item>
          <Descriptions.Item label={t("formItem.status")} contentStyle={{color:STATUS_COLOR_LEVEL[values.status]}} children={STATUS_TYPE[values.status]}/>
          <Descriptions.Item label={t("formItem.caliber")}>{values.alias||isNULL}</Descriptions.Item>
          <Descriptions.Item label={t("formItem.director")}>{values.createdBy}</Descriptions.Item>
          <Descriptions.Item label={t("formItem.creator")}>{values.createdBy}</Descriptions.Item>
          <Descriptions.Item label={t("formItem.createDate")}>
            {moment(values.createdAt).format('YYYY-MM-DD hh:mm:ss')}
          </Descriptions.Item>
        </Descriptions>
        {
          otherOpen && (
            <>
              <PureTableCard title={t("title.metricDefine")} headDivider={true} style={{padding: '5px 0'}}>
                <Descriptions column={5}>
                  <Descriptions.Item label={t("formItem.model")}>{values.modelName}</Descriptions.Item>
                  <Descriptions.Item label={t("formItem.measure")}>{values?.metricDefineByMeasureParams?.measures[0]?.bizName||isNULL}</Descriptions.Item>
                  <Descriptions.Item label={t("formItem.calculations")}>{CALC_TYPE[values?.operations]||isNULL}</Descriptions.Item>
                  <Descriptions.Item label={t("formItem.dataFormat")}>{DATA_TYPE[values.dataFormatType]}</Descriptions.Item>
                  <Descriptions.Item label={t("formItem.decimalPlaces")}>{values.dataFormat?.decimalPlaces}</Descriptions.Item>
                  <Descriptions.Item label={t("formItem.dateDimension")}>{(values?.dimensions||[]).find(v=>v?.type===DIM_TYPE_ENUM.DATETIME)?.description}</Descriptions.Item>
                </Descriptions>
              </PureTableCard>
              {
                persistence &&
                <PureTableCard title={t("title.invokeRule")} headDivider={true} style={{padding: '5px 0'}}>
                  <Descriptions column={4}>
                    <Descriptions.Item label={t("formItem.invokeType")}>{t("title."+(vokeConfig?.type || 'AUTO').toLowerCase())}</Descriptions.Item>
                    <Descriptions.Item label={t("formItem.errorRetry")}>{t("title.null")}</Descriptions.Item>
                    <Descriptions.Item label={t("formItem.period")}>
                      {persistence?.runCycleCode ? t("time."+(persistence?.runCycleCode||'DAY').toLowerCase()) :isNULL}
                    </Descriptions.Item>
                    <Descriptions.Item label={t("formItem.createDate")}>{isNULL}</Descriptions.Item>
                    {
                      false &&
                      <CustomItem label="依赖任务" contentStyle={{display: 'block'}}>
                        <Table columns={columns} dataSource={invokeData} pagination={false} size='small'/>
                      </CustomItem>
                    }
                  </Descriptions>
                </PureTableCard>
              }
            </>
          )
        }
        <Footer onClick={() => {setOtherOpen(!otherOpen)}}>
          { otherOpen ? t("button.fold") : t("button.unfold")} <UpOutlined rotate={otherOpen ? 0 : 180}/>
        </Footer>

        {/** 指标的其他信息 */}
        <ProCard
          tabs={{
            activeKey: tab,
            items: [
              {
                label: t("operation.metricDetail"),
                key: 'tab1',
                children: LogicPanel,
              },
              {
                label: t("operation.metricLineage"),
                key: 'tab2',
                children: (
                  <WorkFlowPanel
                    nodeTypes={{metric:MetricNode}}
                    initialNodes={getNodesState}
                    initialEdges={getEdgesState}
                    style={{height: '43vh',backgroundColor:'white',border:'none'}}
                  />
                ),
              },
              {
                label: t("operation.versionInfo"),
                key: 'tab3',
                children: VersionPanel,
              },
              {
                label: t("operation.invokeRecord"),
                key: 'tab4',
                children: InvokePanel,
              }
            ],
            onChange: onTabChange,
          }}
        />
        <Modal title={t("title.taskLog")} width={1600} open={openLog} onOk={()=>setOpenLog(false)} onCancel={()=>setOpenLog(false)} >
          <LogContainer>
            <pre>
              {logRef.current}
            </pre>
          </LogContainer>
        </Modal>
      </Container>
    </Drawer>
  )
})

const Container = styled.div`
    width: 100%;
    max-height: 93%;
    overflow-y: auto;
    overflow-x: hidden;
`
const Wrapper = styled.div`
    width: 100%;
    display: flex;
    align-items: center;
    box-sizing: border-box;
`

const Title = styled.div`
    font-size: ${p => p.theme.fontSizeLG}px;
    font-weight: bold;
    display: inline-block;
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    box-sizing: border-box;
`

const Extra = styled.div`
    margin-inline-start: auto;
    color: ${p => p.theme.colorTextBase};
    font-weight: normal;
    font-size: 14px;
    box-sizing: border-box;
`
const Footer = styled.a`
    margin-left: 95%;
`
const CustomItem = styled(Descriptions.Item)`
    .ant-descriptions-item {
        .ant-descriptions-item-container {
            .ant-descriptions-item-content {
                display: none;
            }
        }
    }

`
const LogContainer = styled.div`
  height: 70vh;
  width: 100%;
  overflow-y: auto;
  background-color: #f5f5f5;
`
