import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Avatar, Input, List, Spin, Button as AntdButton, Switch, Tooltip, Drawer, Space } from 'antd'
import { createRandomValue } from '../../../renderers/Lion/utils/utils'
import { RendererEnv } from '../../../env'
import { Action, Api, SchemaNode } from '../../../types'
import { Button } from '../../../components'

import Dialog from '../../../components/DragModal'
import { Icon } from '../../../components/icons'
import { RightOutlined } from '@ant-design/icons'
import { SendOutlined, LikeFilled, LikeOutlined, SearchOutlined } from '@ant-design/icons'
import './index.scss'
import { isMobile } from '../../../utils/helper'

interface IProps {
  env: RendererEnv
  pageId: string
  action?: Action
  onTitleChange: (title: string) => void
  render: (region: string, node: SchemaNode, props?: any) => JSX.Element
  data: any,
  paramData: string,
  onClose?: () => void,
  open?: boolean,
  /** 移动端用到并传入的 聊天模式 */
  isChatMode?: boolean
}

interface ChatData {
  id: string
  isUser: boolean
  title: string
  star?: 0 | 1
  description?: SchemaNode
  question?: string
  /** 评价类型  0 点赞 1 点踩 */
  commentType?: string
}

interface ServerApiData {
  commentApi: Api
  historyApi: Api
  historySessionApi: Api
  questionApi: Api
  chatApi: Api
  recommendUrlApi: Api
  title: string
  subDesc: string
  desc: string
}

// type QuestionType = 0 | 1 | 2
type QuestionType = string;

const Ai: React.FC<Omit<IProps, 'visible' | 'onClose'>> = (props) => {
  const [chatDatas, setChatDatas] = useState<ChatData[]>([{ id: 'robot_00', isUser: false, title: '你好，我是你的AI助理' }])

  const [inputValue, setInputValue] = useState<string>()

  // 选择模型的功能暂时隐藏
  const [isChatMode, setIsChatMode] = useState(false);
  const [fetchLoading, setFetchLoading] = useState(false);
  /** 聊天模式的关联上下文的id */
  const [chatConversationId, setChatConversationId] = useState();

  const [commentLoading, setCommentLoading] = useState(false);

  const [recommends, setRecommends] = useState({});
  const serverApiObj = useRef<ServerApiData>()

  const userName: string = JSON.parse(sessionStorage.getItem('userInfo') ?? '{}')?.user_name ?? 'USER'
  useEffect(() => {
    setIsChatMode(props.isChatMode);
  }, [props.isChatMode])
  useEffect(() => {
    initAi();
  }, [])
  /** 初始化AI工具，获取接口 */
  const initAi = async () => {
    const res = await props.env.fetcher(`/api/v1/ai/init?page_id=${props.pageId}`)
    if (res.ok && res.data != null) {
      serverApiObj.current = res.data
      props.onTitleChange(res.data.title)
      setChatDatas(datas => datas.map(data => {
        if (data.id == 'robot_00') {
          return {
            ...data,
            // title: res.data.desc,
            title: '',
            description: {
              type: 'lion-tpl',
              tpl: `<div class="description-box"><div class="title">${res.data.desc}</div>${res.data.subDesc}</div>`
            }
          }
        }
        return data
      }))
      handleGetRecommends();
    } else {
      setChatDatas(datas => datas.map(data => {
        if (data.id == 'robot_00') {
          return {
            ...data,
            description: {
              type: 'lion-tpl',
              tpl: res.msg
            }
          }
        }
        return data
      }))
    }
  }

  const scrollToBottom = () => {
    const element = document.getElementById('sf-chat-list')
    if (element) {
      element.scrollTop = element.scrollHeight
    }
  }
  const generateSearchParam = useCallback(() => {
    const [url, param = ''] = (props.paramData ?? '').split('?');
    return `?${param}`
  }, [props.paramData]);
  /** 获取推荐条目 */
  const handleGetRecommends = async (config?: { chatId?: string; question?: string } = {}) => {
    const { chatId = 'robot_00', question = '' } = config;
    const apiConfig = serverApiObj.current?.['recommendUrlApi'] as Object;
    try {
      const res = await props.env.fetcher({ ...apiConfig }, { question });
      if (res.ok && res.data != null) {
        setRecommends((obj) => ({ ...obj, [chatId]: res.data }));
      }
    } finally {

    }

  }

  const handleSend = async (e, value?: string) => {
    if (fetchLoading) { e.preventDefault(); return; };
    if (value && value?.trim().length > 0) {
      const userId = 'user_' + createRandomValue()
      const robotId = 'robot_' + createRandomValue()
      const userData: ChatData = { id: userId, isUser: true, title: value }
      const robotData: ChatData = { id: robotId, isUser: false, title: '' }
      setChatDatas(datas => datas.concat([userData, robotData]))

      setTimeout(() => {
        requestAnimationFrame(() => {
          setInputValue('');
          scrollToBottom()
        });
      }, 100);
      if (serverApiObj.current) {
        const apiConfig = serverApiObj.current[isChatMode ? 'chatApi' : 'questionApi'] as Object;
        const { url } = apiConfig;
        const params = { question: value, ...(isChatMode ? { conversationId: chatConversationId } : {}) };
        const fetchUrl = `${url}${!isChatMode ? generateSearchParam() : ''}`;
        try {
          setFetchLoading(true);
          const res = await props.env.fetcher({ ...apiConfig, url: fetchUrl }, params)
          if (res.ok && res.data != null) {
            /** 如果是聊天模式，则直接显示answer */
            if (isChatMode) {
              const { aiPagePanel, sasAiChat } = res.data;
              const { conversationId } = sasAiChat;
              setChatConversationId(conversationId);
              setChatDatas(datas => datas.map(data => data.id == robotId ? { ...data, description: aiPagePanel?.body, id: conversationId } : data))

            } else {
              const { aiPagePanel, sasAiChat } = res.data
              setChatDatas(datas => datas.map(data => data.id == robotId ? { ...data, description: aiPagePanel?.body, id: sasAiChat?.chatId ?? data.id, question: value } : data))
              handleGetRecommends({ ...sasAiChat, question: value });

            }

          } else {
            setChatDatas(datas => datas.map(data => data.id == robotId ? {
              ...data, description: {
                type: 'lion-tpl',
                tpl: res.msg
              }
            } : data))
          }
        } finally {
          setFetchLoading(false);
        }
      }
    }
  }
  const genSendIconClassName = useCallback(() => {
    return `icon-send ${inputValue?.length && !fetchLoading ? '' : 'disabled'}`;
  }, [inputValue, fetchLoading]);
  /** 评论AI的答复 */
  const handleCommentItem = async (config: { question: string, commentType: number, chatId: string }) => {
    /** commentType: 0 点赞  1 点踩 */
    if (commentLoading) return;
    const { chatId, commentType, ...params } = config;
    try {
      setCommentLoading(true);
      const res = await props.env.fetcher(serverApiObj.current?.['commentApi'] as any, { ...params, pageId: props.pageId });
      if (res.ok) {
        setChatDatas((datas) => datas.map((data) => data.id === chatId ? { ...data, commentType: `${commentType}` } : data))
      }
    } finally {
      setCommentLoading(false);
    }
  }
  /** 支持 shift + enter 插入换行 */
  const handleBreakLine = (e) => {
    if (!e.shiftKey && e.keyCode === 13) {
      e.preventDefault();
      handleSend(e, inputValue)
    }
  }

  const commentTypeTextMap = {
    0: '赞',
    1: '踩'
  }
  const listRender = useMemo(() => {
    return (
      <List
        className='chat-list'
        id='sf-chat-list'
        rowKey={'id'}
        dataSource={chatDatas}
        split={false}
        renderItem={data => {
          const { id, isUser, title, description, question = '', commentType } = data

          return (
            <List.Item className={isUser ? 'item-user' : 'item-ai'}>
              <List.Item.Meta
                className={isUser ? 'meta-user' : 'meta-ai'}
                style={{ flexDirection: isUser ? 'row-reverse' : 'row' }}
                avatar={<Avatar shape="square" size={32} src={isUser ? undefined : './public/images/zhilong.png'} icon={<span>{isUser ? userName.substring(0, 1) : 'AI'}</span>} />}
                title={title?.length ?<div className='description-box' id={id}>{title}</div> : null}
                // title={false}
                description={
                  <div>
                    {
                      !isUser ? description ? (
                        <div>
                          {props.render(createRandomValue(), description, { aiQuery: props.data, onAiFinished: () => { scrollToBottom() } })}
                          {
                            id.startsWith('robot_00') ? (
                              <div className='recommend-box-init'>
                                {recommendRender(id)}
                              </div>
                            ) : null
                          }
                        </div>
                      ) : <div className='description-box'><Spin /></div> : null
                    }
                    {/* {!isUser ? description ?  : <Spin /> : undefined} */}

                    <div className='bottom-operate-box'>

                      {!isUser && id && id !== 'robot_00' && description && !isChatMode && (
                        <div className={`ai-btn-groups ${commentType ? 'checked' : ''}`}>
                          {
                            commentType ? (
                              <>
                                <div className='comment-btn'>
                                  <LikeFilled style={{ color: commentType === '0' ? '#fda71e' : '#999' }} rotate={commentType === '1' ? 180 : 0} />
                                  <span className='text'>{commentTypeTextMap[commentType]}</span>
                                </div>
                              </>
                            ) : (
                              <>
                                <div className='comment-btn like' onClick={() => handleCommentItem({ question, commentType: 0, chatId: id })}>
                                  <LikeOutlined /> <span className='text'>{commentTypeTextMap[0]}</span>
                                </div>

                                <div className='comment-btn dislike' onClick={() => handleCommentItem({ question, commentType: 1, chatId: id })}>
                                  <LikeOutlined rotate={180} /> <span className='text'>{commentTypeTextMap[1]}</span>
                                </div>
                              </>
                            )
                          }

                        </div>
                      )}
                    </div>
                  </div>

                }
              />
              {
                !isUser && !id.startsWith('robot_00') && (<>{recommendRender(id)}</>)
              }
            </List.Item>
          )
        }}
      />
    )
  }, [chatDatas, commentLoading, recommends]);
  const handleSendRecommend = (e, question: string, id: string) => {
    setRecommends((obj) => ({ ...obj, [id]: undefined }))
    handleSend(e, question);
  }
  const recommendRender = (id: string = 'robot_00') => {
    const render = recommends[id]?.map((item: { question: string; count: number }) => {
      const { question = '' } = item;
      return (
        <div className="recommend-item" onClick={(e) => handleSendRecommend(e, question, id)}>
          <div>{question}</div>
          <div className='icon-box'>
            <RightOutlined style={{ color: 'rgba(0,0,0, 0.6', fontSize: '12px' }} />
          </div>
        </div>
      )
    });

    return (<div className='recommend-box'>{render}</div>);
  }
  return (
    <div className='ai-tool-container'>
      {listRender}
      <div className='chat-footer'>
        {
          isMobile() ? (
            <div className="footer-box">
              <div className="icon-prefix-box">
                <Icon icon="#icon-toolailoong" className="icon-send-prefix" symbol />
              </div>
              <Input.TextArea
                bordered={false}
                className='word-inp'
                autoSize={{ minRows: 1, maxRows: 3 }}
                placeholder='Enter发送'
                value={inputValue}
                onFocus={scrollToBottom}
                // allowClear
                // onPressEnter={(e) => { handleSend(e, inputValue) }}
                onChange={e => setInputValue(e.target.value)}
              />
              <AntdButton type='link' className={genSendIconClassName()} onClick={(e) => { handleSend(e, inputValue) }}><SendOutlined /></AntdButton>

            </div>
          ) : (
            <div className="footer-box">
              {/* <div className="icon-prefix-box">
                <Icon icon="#icon-toolailoong" className="icon-send-prefix" symbol />
              </div> */}
              <Input.TextArea
                className='word-inp'
                autoSize={{ minRows: 3, maxRows: 4 }}
                bordered={false}
                // style={{ height: 32, border: 'none', }}
                placeholder='按Enter发送、Shift + Enter换行'
                value={inputValue}
                onKeyDown={handleBreakLine}
                onChange={e => setInputValue(e.target.value)}
                allowClear
              />
              <div className="bottom-box">
                <div >
                  <Switch size='small' onChange={setIsChatMode} /> 聊天模式
                </div>
                <AntdButton type='link' className={genSendIconClassName()} onClick={(e) => { handleSend(e, inputValue) }}><SendOutlined /></AntdButton>
              </div>
            </div>

          )
        }
      </div>
    </div>
  )
}

export default (props: Omit<IProps, 'onTitleChange'>) => {

  const { action, onClose } = props
  const [open, setOpen] = useState(false)
  const [hide, setHide] = useState(true)
  const [showFixModal, setShowFixModal] = useState(false);
  const [title, setTitle] = useState<string | React.ReactElement>('智龙助理')
  const [isChatMode, setIsChatMode] = useState(false)
  const updateTitle = (titleText: string) => {
    const newTitle = (<><div className='table-icon-box'><Icon icon="#icon-toolailoong" className="icon" symbol /></div><span className='title-text'>{titleText}</span></>)
    setTitle(newTitle);
  }
  return (
    <>
      {
        !isMobile() ? (
          <>
            <Button
              onClick={() => {
                open && setShowFixModal(open); setOpen(true); hide && setHide(false);
                requestAnimationFrame(() => {
                  setShowFixModal(false);
                });
              }}>
              <Icon icon={"#icon-toolailoong"} className="icon" symbol />
              {action?.label}
            </Button>
            {open && <Dialog
              className='ai-tool-drawer'
              width={500}
              minWidth={400}
              minHeight={500}
              setFixRight={false}
              dialogVisible={open}
              mask={false}
              showMinTitle={true}
              title={title}
              resizeable={true}
              centered={true}
              canClickBelowDom
              setMaxSize={true}
              forceCalcOnResize
              pinRight
              hide={hide}
              onHide={() => { setHide((true)); }}
              onShow={() => { setHide(false); setOpen(true) }}
              onCancel={() => { setHide(false); setOpen(false) }}
              bodyStyle={{ padding: 0, height: 'calc(100vh - 200px)' }}
              maskClosable={false}
              footer={null}
              keyboard={false}
              fullHeightOnInit
              // cacheConfigKey="MODAL_AI_TOOL_CONFIG"
              miniTitleWrapperClassName="aitool-dialog-wrapper"
              getContainer={(props.env.container ?? props.env.getModalContainer) as () => HTMLElement}
              forceShowFixModal={showFixModal}
              hiddenBtn={
                <Icon icon="#icon-toolailoong" className="ai-hidden-btn" symbol />
              }
            >
              <Ai {...props} onTitleChange={updateTitle} />
            </Dialog>
            }</>
        ) : (
          <>
            {open ? (<Drawer
              placement='top'
              mask
              width='100vw'
              height='100vh'
              getContainer={(props.env.container ?? props.env.getModalContainer) as () => HTMLElement}
              open={open}
              className="ai-tool-drawer"
              title={title}
              extra={
                <div className='chat-mode-box'>
                  <Switch className='chat-mode-switch' checked={isChatMode} onChange={setIsChatMode} checkedChildren="聊天" unCheckedChildren="查询" />
                </div>
              }
              onClose={() => { setOpen(false); onClose?.() }}
            >
              <div className="ai-tool-mobile-wrapper">
                <Ai {...props} onTitleChange={updateTitle} isChatMode={isChatMode} />
              </div>
            </Drawer>) : null}
            <div className='toolbar-item' onClick={() => setOpen(true)}>
              <div className='toolbar-item-icon'><Icon icon={action?.icon} ></Icon></div>
              <div className='toolbar-item-name'>{action?.label}</div>
            </div>
          </>
        )
      }
    </>
  )

}
