import { ContainerEdit } from '@kevisual/container/edit';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router';
import { query, useStore, ws } from '@/modules';
import { Button, message, Tooltip } from 'antd';
import { getContainerData } from '@/modules/deck-to-flow/deck';
import { usePanelStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
import { TextArea } from '@/pages/container/components/TextArea';
import { CloseOutlined, MessageOutlined, SaveOutlined, SelectOutlined } from '@ant-design/icons';
import { useDeckPageStore } from './deck-store';
import { FormModal } from './Model.tsx';
import { useAiStore } from '@/pages/ai-chat/index.tsx';
export const clearBlank = (newStyle: any) => {
  let change = false;
  for (let key in newStyle) {
    if (newStyle[key] === '' || newStyle[key] === undefined || newStyle[key] === null) {
      delete newStyle[key];
      change = true;
    }
  }
  return change;
};
export const useListener = (id?: string, opts?: any) => {
  const { refresh, cids = [] } = opts || {};
  const connected = useStore((state) => state.connected);
  // 监听服务器的消息
  useEffect(() => {
    if (!id) return;
    if (!connected) return;
    if (cids.length === 0) return;
    console.log('cids', cids);
    ws.send(
      JSON.stringify({
        type: 'subscribe',
        data: {
          type: 'pageEdit',
          data: {
            pid: id,
            cids: cids,
          },
        },
      }),
    );
    ws.addEventListener('message', listener);
    return () => {
      if (!id) return;
      if (!connected) return;
      ws.removeEventListener('message', listener);
    };
  }, [id, connected, cids]);
  const listener = (event) => {
    const parseIfJson = (data: string) => {
      try {
        return JSON.parse(data);
      } catch (e) {
        return data;
      }
    };
    const receivedData = parseIfJson(event.data);
    if (typeof receivedData === 'string') return;
    if (receivedData.type === 'pageEdit' && receivedData.source === 'container') {
      const { data: containerData, pid } = receivedData;
      if (pid !== id) return;
      if (refresh) {
        refresh(containerData);
      }
    }
  };
};

export const Deck = () => {
  const params = useParams<{ id: string }>();
  const id = params.id;
  const ref = useRef<HTMLDivElement>(null);
  const containerRef = useRef<ContainerEdit | null>(null);
  const deckPageStore = useDeckPageStore();
  const { code, setCode } = deckPageStore;
  const { selected, setSelected } = deckPageStore;
  const { cids } = deckPageStore;
  const aiStore = useAiStore(
    useShallow((state) => {
      return {
        setOpen: state.setOpen,
        setKey: state.setKey,
      };
    }),
  );
  const panelStore = usePanelStore(
    useShallow((state) => {
      return {
        updateNodeDataStyle: state.updateNodeDataStyle,
      };
    }),
  );
  useEffect(() => {
    if (!id) return;
    deckPageStore.setId(id);
    fetch();
  }, []);
  useEffect(() => {
    ref.current?.addEventListener('onContainer', onContainer);
    return () => {
      ref.current?.removeEventListener('onContainer', onContainer);
      if (ref.current) {
        const children = ref.current;
        children.innerHTML = '';
      }
    };
  }, []);
  const fetch = async () => {
    const res = await query.post({
      path: 'page',
      key: 'getDeck',
      id,
    });
    if (res.code === 200) {
      const data = res.data;
      console.log('data', data);
      const { page, containerList } = data;
      const result = getContainerData({ page, containerList });
      console.log('result', result);
      deckPageStore.setPageData(result);
      deckPageStore.setCids();
      init(result);
    }
  };
  const refresh = async (data: any) => {
    console.log('refresh', data);
    if (!data.id) return;
    const code = {
      codeId: data.id,
      code: data.code,
      hash: '',
    };
    const container = containerRef.current!;
    // @ts-ignore
    await container.updateDataCode([code]);
    const containerList = container.data.filter((item) => item.codeId === data.id);
    await new Promise((resolve) => {
      setTimeout(resolve, 2000);
    });
    // container.reRender();
    containerList.forEach((item) => {
      container.renderId(item.id);
    });
    // @ts-ignore
    window.c = container;
  };
  useListener(id, { refresh, cids });
  const onContainer = (e) => {
    const { data } = e;
    const types = ['position', 'resize'];
    if (types.includes(data.type)) {
      const { type, data: containerData } = data;
      if (type === 'position') {
        const { cid, left, top, rid } = containerData;
        const newData = {
          id: rid,
          nodeData: {
            id: cid,
            data: {
              style: {
                // position: 'absolute',
                left,
                top,
              },
            },
          },
        };
        if (left && top) {
          panelStore.updateNodeDataStyle(newData);
        }
        updateStyle(cid, { left, top });
        setTimeout(() => {
          setCodeStyle(cid);
        }, 1000);
      } else if (type === 'resize') {
        const { cid, rid, width, height } = containerData;
        const newData = {
          id: rid,
          nodeData: {
            id: cid,
            data: {
              style: {
                width,
                height,
              },
            },
          },
        };
        if (width && height) {
          // @ts-ignore
          newData.nodeData.data.style.position = 'absolute';
          panelStore.updateNodeDataStyle(newData);
        }
        updateStyle(cid, { width, height });
        setTimeout(() => {
          setCodeStyle(cid);
        }, 1000);
      }
    } else if (data.type === 'active') {
      if (!data?.data?.cid) {
        setSelected(null);
        return;
      }
      const { cid, rid } = data?.data || {};
      setSelected(data);
      setCodeStyle(cid);
    } else {
      console.log('onContainer', data);
    }
  };
  const onSave = () => {
    const { cid, rid } = selected?.data || {};
    let data: any;
    try {
      data = JSON.parse(code);
    } catch (error) {
      message.error('JSON format error');
      return;
    }
    // clearBlank(data);
    const newData = {
      id: rid,
      nodeData: {
        id: cid,
        data: {
          style: data,
        },
      },
    };
    panelStore.updateNodeDataStyle(newData, true);
    const newDataStyle = updateStyle(cid, data);
    reRender(newDataStyle, cid);
  };
  const setCodeStyle = (cid: string) => {
    const pageData = deckPageStore.getPageData();
    const selected = deckPageStore.getSeleted();
    const _data = pageData.find((item) => item.id === cid);
    const node = _data?.data?.node || {};
    if (selected?.data?.cid === cid) {
      setCode('');
      setCode(JSON.stringify(node?.data?.style || {}, null, 2));
    }
  };
  useEffect(() => {
    if (selected) {
      const { cid } = selected?.data || {};
      cid && setCodeStyle(cid);
    }
  }, [deckPageStore.selected]);

  const updateStyle = (rid: string, style: any) => {
    const pageData = deckPageStore.getPageData();
    const _pageData = pageData.map((item) => {
      if (item.id === rid) {
        const newStyle = {
          ...item.data.node.data.style,
          ...style,
        };
        // 过滤掉空的style
        clearBlank(newStyle);
        return {
          ...item,
          style: newStyle,
          data: {
            ...item.data,
            node: {
              ...item.data.node,
              data: {
                ...item.data.node.data,
                style: newStyle,
              },
            },
          },
        };
      }
      return item;
    });
    deckPageStore.setPageData([..._pageData]);
    return _pageData;
  };
  const init = async (data: any[]) => {
    // console.log('data', data, ref.current);
    const container = new ContainerEdit({
      root: ref.current!,
      data: data,
      showChild: true,
      // edit: false,
    });
    container.render(id!);
    containerRef.current = container;
    containerRef.current.event.on('save', (data) => {
      console.log('save', data);
      const { id, code } = data;
    });
  };
  const reRender = async (data: any[], cid?: string) => {
    if (containerRef.current) {
      const container = containerRef.current;
      await container.updateData(data);
      await container.renderId(cid!);
      return;
    }
  };
  return (
    <div className='w-full h-full relative'>
      <div className='w-full h-full bg-gray-200 '>
        <div className='text-center mb-10 font-bold text-4xl pt-4 flex items-center justify-center group'>
          Deck
          <Tooltip>
            <Button
              className='ml-4 invisible group-hover:visible'
              icon={<SelectOutlined />}
              onClick={() => {
                deckPageStore.setShowEdit(true);
              }}></Button>
          </Tooltip>
        </div>
        <div
          className='flex '
          style={{
            height: 'calc(100% - 32px)',
          }}>
          <div className='mx-auto border  rounded-md bg-white  w-[80%] h-[80%] scrollbar overflow-scroll relative' ref={ref}></div>
        </div>
      </div>
      {selected && (
        <div className='absolute bottom-5 z-50 w-full h-[200px]'>
          <div className=' p-2 card w-[80%]  mx-auto border bg-slate-200 rounded-md overflow-scroll scrollbar'>
            {/* <pre>{JSON.stringify(selected, null, 2)}</pre> */}
            <div>
              <Button.Group>
                <Tooltip title='Close'>
                  <Button
                    onClick={() => {
                      setSelected(null);
                    }}
                    icon={<CloseOutlined />}></Button>
                </Tooltip>
                <Tooltip title='Ai Chat'>
                  <Button
                    onClick={() => {
                      aiStore.setOpen(true);
                      aiStore.setKey(location.pathname);
                    }}
                    icon={<MessageOutlined />}></Button>
                </Tooltip>
                <Tooltip title='Save'>
                  <Button
                    onClick={() => {
                      onSave();
                    }}
                    icon={<SaveOutlined />}></Button>
                </Tooltip>
              </Button.Group>
            </div>
            <div className='h-[200px]'>
              <TextArea
                className='h-[100px] rounded-md'
                value={code}
                onChange={(v) => {
                  setCode(v);
                }}
              />
            </div>
          </div>
        </div>
      )}
      <FormModal />
    </div>
  );
};
