/* eslint-disable @typescript-eslint/no-unused-expressions */
import {
  Form,
  Button,
  Col,
  Row,
  Input,
  Typography,
  Grid,
  message,
  Space,
  Modal,
  Divider,
} from 'antd';
import React, { useState, useEffect, useRef, useMemo } from 'react';
import styles from './index.less';
import ChatFirstContent from './components/content';
import {
  LoadingOutlined,
  LockOutlined,
  LogoutOutlined,
  MenuOutlined,
  PlusOutlined,
  SettingOutlined,
  UserOutlined,
} from '@ant-design/icons';
import classNames from 'classnames';
import { history } from 'umi';
import LoginModal from '@/components/LoginModal';
import NewSession from '@/components/NewSession';
import { useWebSocket, useRequest } from 'ahooks';
import {
  GetChatGLMToken,
  GetPromptList,
  createSession,
  postResetUser,
  updateSession,
} from '@/services/chatGLM/api';
import { useAccess } from 'umi';
import { PageLoading } from '@ant-design/pro-layout';
import { checkIsTokenExpires } from '@/access';
import TextArea from 'antd/lib/input/TextArea';
import Password from 'antd/lib/input/Password';

const { useBreakpoint } = Grid;
const { Title } = Typography;
const { Item } = Form;

const isMobileDevice = (): boolean => {
  const ua = navigator.userAgent;
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
};

interface IHistory {
  prompt: string;
  answer: string;
}

const Chat: React.FC = () => {
  const screens = useBreakpoint();
  const isMobile = screens.xs;
  const [sessionId, setSessionId] = useState<string>('');
  const [chat, setChat] = useState('');
  const [showSider, setShowSider] = useState(!isMobileDevice());
  const [firstChat, setFirstChat] = useState(false);
  const [form] = Form.useForm();
  const [resetForm] = Form.useForm();
  const [resetPasswordModal, setResetPasswordModal] = useState(false);
  const [restLoading, setResetLoading] = useState(false);
  const { data: glmToken, run: getChatGLMToken } = useRequest(GetChatGLMToken, { manual: true });
  const {
    data: promptList,
    loading: promptLoading,
    run: getPromptList,
  } = useRequest(GetPromptList, { manual: true });

  const [answer, setAnswer] = useState('');
  const [loading, setLoading] = useState(true);
  const [loginModalOpen, setLoginModalOpen] = useState(false);
  const access = useAccess();

  const messageHistory = useRef<IHistory[]>([]);
  const { sendMessage } = useWebSocket('wss://glm-api.baibaomen.com/ws', {
    onMessage: (event) => {
      const text = event.data;
      if (text == '{{BBMCPLT}}') {
        setLoading(false);
        createChatSession();
      } else {
        setAnswer(text);
        window.scrollTo(0, document.body.scrollHeight);
      }
    },
    onOpen: () => {
      console.log('connected!');
      setLoading(false);
    },
    onError: () => {
      setLoading(false);
    },
  });

  function createChatSession() {
    if (sessionId) {
      updateSession({ id: sessionId, content: JSON.stringify(messageHistory.current) });
    } else {
      createSession({ content: JSON.stringify(messageHistory.current) }).then((data) => {
        data?.id && setSessionId(data.id);
      });
    }
  }

  messageHistory.current = useMemo(() => {
    if (messageHistory.current.length > 0)
      messageHistory.current[messageHistory.current.length - 1].answer += answer;
    return messageHistory.current;
  }, [answer]);

  async function handleSendMessage() {
    if (!checkIsTokenExpires()) {
      messageHistory.current.push({ prompt: chat, answer: '' });
      setLoading(true);
      sendMessage &&
        glmToken &&
        sendMessage(
          JSON.stringify({
            prompt: chat,
            max_length: 2048,
            top_p: 0.7,
            temperature: 0.95,
            history: [messageHistory.current.map((h) => h.prompt)],
            token: glmToken,
          }),
        );
    }
  }

  function newChat() {
    messageHistory.current.splice(0, messageHistory.current.length || 0);
    isMobile && setShowSider(false);
    setFirstChat(false);
  }

  useEffect(() => {
    if (access?.token) {
      getChatGLMToken();
      getPromptList();
      setLoginModalOpen(false);
    } else {
      setLoginModalOpen(true);
    }
  }, [access]);

  const onSend = () => {
    form.setFieldValue('chatInput', '');
    setFirstChat(true);
    handleSendMessage();
  };

  const setInput = (value: any) => {
    setChat(value?.firstInput);
    form.setFieldValue('chatInput', value?.firstInput);
  };

  const onChange = (value: any) => {
    value?.chatInput && setChat(value?.chatInput);
    value?.firstInput && setInput(value);
  };

  const renderMobileHeader = () => {
    return (
      <Row align={'middle'} justify="space-between" gutter={1} className={styles.mobileHeader}>
        <Col push={1}>
          <MenuOutlined
            onClick={() => {
              setShowSider(!showSider);
            }}
          />
        </Col>
        <Col>ZENSONG.AI</Col>
        <Col pull={1} />
      </Row>
    );
  };

  const validatePassword = (_, value: any) => {
    const regex =
      /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z\d!@#$%^&*()_+}{":?><,./;'\[\]\\=-]{8,16}$/;
    if (regex.test(value)) {
      return Promise.resolve();
    }
    return Promise.reject(new Error('密码必须包含数字、大小写字母且长度为8-16位'));
  };

  const handleFinish = (values: any) => {
    setResetLoading(true);
    const data = {
      id: JSON.parse(localStorage.getItem('user') || '')?.id,
      Password: values?.newPassword,
    };
    postResetUser(data)
      .then(() => {
        setResetLoading(false);
        setResetPasswordModal(false);
        resetForm.resetFields();
        message.success('重置成功');
        setTimeout(() => {
          logout();
        }, 1000);
      })
      .catch(() => {
        setResetLoading(false);
      });
  };

  const logout = () => {
    localStorage.removeItem('user');
    localStorage.removeItem('account');
    localStorage.removeItem('expires');
    setLoginModalOpen(true);
  };

  return (
    <>
      <LoginModal open={loginModalOpen} setOpen={setLoginModalOpen} />
      {isMobile && renderMobileHeader()}
      <Row>
        <Col className={`${styles.siderWrapper}`}>
          {isMobile && showSider && (
            <div
              onClick={() => {
                setShowSider(false);
              }}
              className={styles.siderMask}
            ></div>
          )}
          <div
            style={{ top: isMobile && '44px', zIndex: isMobile ? 13 : 10 }}
            className={`${styles.sider} ${showSider ? styles.siderOpen : ''}`}
          >
            <div className={styles.siderChatContent}>
              <div style={{ padding: '30px 20px 0 20px' }}>
                <Button size="large" block type="primary" icon={<PlusOutlined />} onClick={newChat}>
                  新的对话
                </Button>
              </div>
            </div>
            <Row
              className={styles.chatFooter}
              style={{ width: '240px', marginBottom: isMobile ? 80 : 60 }}
              justify={'center'}
              align={'middle'}
            >
              <Col
                span={24}
                className={styles.chatFooterItem}
                hidden={!access.roles?.find((x: string) => ['管理员', 'admin'].includes(x))}
                onClick={() => {
                  history.push('/welcome');
                }}
              >
                <Space wrap>
                  <SettingOutlined />
                  后台管理
                </Space>
              </Col>
              <Col span={24} hidden={loginModalOpen} className={styles.chatFooterItem}>
                <Space
                  wrap
                  onClick={() => {
                    setResetPasswordModal(true);
                  }}
                >
                  <LockOutlined />
                  重置密码
                </Space>
              </Col>
              <Col span={24} className={styles.chatFooterItem} style={{ color: '#009B95' }}>
                <Space wrap>
                  <UserOutlined />
                  {access?.name || '请先登录'}
                </Space>
              </Col>
              <Col
                hidden={loginModalOpen}
                span={24}
                className={styles.chatFooterItem}
                onClick={logout}
              >
                <Space wrap>
                  <LogoutOutlined />
                  退出登录
                </Space>
              </Col>
            </Row>
          </div>
        </Col>
        <Form
          form={form}
          initialValues={{ chatInput: chat }}
          name="chat"
          onValuesChange={onChange}
          onFinish={onSend}
        >
          <Col
            className={styles.chatContent}
            style={{
              marginLeft: isMobile ? 0 : 240,
              width: isMobile ? 'calc(100vw)' : 'calc(100vw - 240px)',
            }}
          >
            <Row justify={'center'}>
              <Col span={'24'}>
                {!isMobile && (
                  <div className={styles.header} hidden={firstChat}>
                    <Row>
                      <Col
                        span={24}
                        style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
                      >
                        <img
                          style={{ marginRight: 12, height: 40, marginBottom: 6 }}
                          src="https://baibaomen.oss-cn-hangzhou.aliyuncs.com/zhensheng/Logo.png"
                          alt="logo"
                        />
                        <Title level={2} style={{ marginBottom: 8, fontSize: 32 }}>
                          ZENSONG.AI
                        </Title>
                      </Col>
                      <Col span={24}>
                        <Title level={5} className={styles.subTitle}>
                          AI智能小助手
                        </Title>
                      </Col>
                    </Row>
                  </div>
                )}
              </Col>
              {promptLoading && (
                <Col span={24}>
                  <PageLoading />
                </Col>
              )}
              <Col span={'24'} style={{ padding: isMobile ? '' : '0 100px' }}>
                {firstChat ? (
                  <div style={{ marginBottom: 150 }}>
                    {messageHistory.current.map((item, index) => (
                      <NewSession
                        onRetry={(value) => {
                          setChat(value);
                          handleSendMessage();
                        }}
                        key={'new' + index}
                        questionValue={item.prompt}
                        answerValue={item.answer}
                      />
                    ))}
                  </div>
                ) : (
                  <div className={classNames(isMobile && styles.mobileContent)}>
                    <Item name="firstInput">
                      <ChatFirstContent list={promptList?.items || []} />
                    </Item>
                  </div>
                )}
              </Col>

              <div
                className={styles.footer}
                style={{
                  marginLeft: isMobile ? 0 : '240px',
                  height: isMobile ? '100px' : '120px',
                  width: isMobile ? '100vw' : 'calc(100vw - 240px)',
                }}
              >
                <Row justify={'center'} align={'middle'} style={{ textAlign: 'center' }}>
                  <Col span={24} style={{ textAlign: 'center', marginTop: 12 }}>
                    <Space style={{ textAlign: 'center', height: 40 }}>
                      <div
                        className={styles.chatWrapper}
                        style={{
                          marginLeft: firstChat && !isMobile ? '82px' : 0,
                          width: isMobile
                            ? 'calc(100vw - 108px)'
                            : firstChat
                            ? 'calc(100vw - 482px)'
                            : 'calc(100vw - 550px)',
                        }}
                      >
                        <Item name="chatInput">
                          {isMobile ? (
                            <TextArea
                              autoSize={{ minRows: 1, maxRows: 2 }}
                              required
                              placeholder={'在这里输入你想知道的问题'}
                              size="large"
                            />
                          ) : (
                            <Input required placeholder={'在这里输入你想知道的问题'} size="large" />
                          )}
                        </Item>
                      </div>
                      <div className={styles.outputButtonWrapper}>
                        <Item name="outputButton">
                          <Button htmlType="submit" type="primary" size="large" disabled={loading}>
                            {loading ? (
                              <>
                                &nbsp;
                                <LoadingOutlined />
                                &nbsp; &nbsp;
                              </>
                            ) : (
                              '发送'
                            )}
                          </Button>
                        </Item>
                      </div>
                    </Space>
                  </Col>
                  <Col span={24}>
                    <span style={{ color: '#999', fontSize: 13, marginTop: isMobile ? 10 : 0 }}>
                      技术支持方 ChatMAP.AI
                    </span>
                  </Col>
                </Row>
              </div>
            </Row>
          </Col>
        </Form>
      </Row>
      <Modal
        closable={true}
        title="重置密码"
        destroyOnClose={true}
        open={resetPasswordModal}
        onCancel={() => {
          setResetPasswordModal(false);
        }}
        footer={null}
      >
        <Form form={resetForm} onFinish={handleFinish} name="resetPassword">
          <Item
            name={'newPassword'}
            label={'新密码'}
            rules={[{ required: true, message: '请输入密码' }, { validator: validatePassword }]}
          >
            <Password placeholder="请输入6-12位的数字或者字母" />
          </Item>
          <Item
            name={'confirmNewPassword'}
            label={'确认新密码'}
            rules={[
              {
                required: true,
                message: '请确认你的密码',
              },
              ({ getFieldValue }) => ({
                validator(_, value) {
                  if (!value || getFieldValue('newPassword') === value) {
                    return Promise.resolve();
                  }
                  return Promise.reject(new Error('两次密码输入不一致'));
                },
              }),
            ]}
          >
            <Password placeholder="请确认你的新密码" />
          </Item>
          <Divider />
          <Row justify={'center'}>
            <Col>
              <Item key={'saveButton'} noStyle={true}>
                <Button key="submit" type="primary" loading={restLoading} htmlType="submit">
                  重置
                </Button>
              </Item>
            </Col>
          </Row>
        </Form>
      </Modal>
    </>
  );
};

export default Chat;
