import {
  Bubble,
  Prompts,
  Sender,
  Suggestion,
  XProvider,
  Welcome,
  Attachments,
  AttachmentsProps,
} from "@ant-design/x";
import { useChat } from "@/hooks/useChat";
import "./index.less";

import {
  Card,
  Flex,
  message,
  Button,
  Space,
  Spin,
  Typography,
  Tooltip,
} from "antd";
import { useEffect, useRef, useState } from "react";
import {
  BulbOutlined,
  SmileOutlined,
  UserOutlined,
  CloudUploadOutlined,
  LinkOutlined,
  CopyOutlined,
  RedoOutlined,
  ReadOutlined,
  FireOutlined,
  ClearOutlined,
} from "@ant-design/icons";
import type { GetProp, GetRef } from "antd";
import MarkdownViewer from "@/components/ai/MarkdownViewer";
import GenerateBubble from "./components/GenerateBubble";

// bubbles角色配置
const roles: GetProp<typeof Bubble.List, "roles"> = {
  assistant: {
    placement: "start",
    avatar: {
      icon: <i className="iconfont icon-AI1" />,
      style: { background: "#3450ec" },
    },
    // typing: { step: 5, interval: 20 },
    loadingRender: () => (
      <Space>
        <Spin size="small" />
        思考中...
      </Space>
    ),
    messageRender: (content) => {
      return typeof content === "string" ? (
        <Typography className={content?.includes("```") ? "w-full" : ""}>
          <MarkdownViewer content={content} />
        </Typography>
      ) : (
        content
      );
    },
    header: "易码工坊AI助手",
    styles: {
      content: {
        background: "#fff",
        width: "100%",
        border: "1px solid #e2ecfc",
        boxShadow: "0 0 4px rgba(0, 0, 0, 0.12)",
      },
    },
  },
  user: {
    placement: "start",
    avatar: { icon: <UserOutlined />, style: { background: "#87d068" } },
    messageRender: (content) => {
      return <div style={{ whiteSpace: "pre-wrap" }}>{content}</div>;
    },
    styles: {
      content: {
        background: "#e2ecfc",
        border: "1px solid #e2ecfc",
        boxShadow: "0 0 4px rgba(0, 0, 0, 0.12)",
      },
    },
  },
};

export default () => {
  const [senderVal, setSenderVal] = useState("");
  const {
    messages,
    setMessages,
    activeConversation,
    changeConversation,
    conversationList,
    onRequest,
    cancel,
    loading,
    loadingSession,
    addConversation,
    setConversationList,
  } = useChat({
    app_name: "app_generate",
    onSuccess: (msg) => {
      setMessages((messages) => {
        const arr = [...messages];
        const query = arr[messages.length - 2].content as string;
        arr[messages.length - 1].status = "done";
        arr[messages.length - 1].footer = (
          <BubbleFooter
            content={arr[messages.length - 1].content as string}
            query={query}
          />
        );
        return arr;
      });
      setTimeout(() => {
        const scrollHeight = listRef.current?.nativeElement?.scrollHeight;
        listRef.current?.nativeElement?.scrollTo({
          top: scrollHeight,
          behavior: "smooth",
        });
      }, 200);
    },
    onUpdate: (msg) => {
      setMessages((messages) => {
        const arr = [...messages];
        arr.forEach((item) => {
          if (item.footer) {
            item.footer = null;
          }
        });
        arr[messages.length - 1].content += msg.answer;
        arr[messages.length - 1].id = msg.message_id;
        arr[messages.length - 1].loading = false;
        arr[messages.length - 1].status = "error";
        return arr;
      });
    },
    onError: (error) => {
      message.error(error.message);
      setMessages((messages) => {
        const arr = [...messages];
        arr[messages.length - 1].content = (
          <Typography.Text type="danger">{error.message}</Typography.Text>
        );
        arr[messages.length - 1].status = "error";
        arr[messages.length - 1].loading = false;
        return arr;
      });
    },
  });

  const [openAttachment, setOpenAttachment] = useState(false);
  const attachmentsRef = useRef<GetRef<typeof Attachments>>(null);
  const senderRef = useRef<GetRef<typeof Sender>>(null);
  const [attachmentItems, setAttachmentItems] = useState<
    GetProp<AttachmentsProps, "items">
  >([]);
  const contentRef = useRef<HTMLDivElement>(null);
  const [contentHeight, setContentHeight] = useState(0);

  const setHeight = () => {
    setContentHeight(contentRef.current?.clientHeight || 0);
  };
  useEffect(() => {
    setHeight();
    const resizeObserver = new ResizeObserver(() => {
      setHeight();
    });
    resizeObserver.observe(contentRef.current!);
    return () => {
      resizeObserver.disconnect();
    };
  }, []);
  const listRef = useRef<GetRef<typeof Bubble.List>>(null);

  // 附件组件
  const senderHeader = (
    <Sender.Header
      title="附件"
      styles={{
        content: {
          padding: 0,
        },
      }}
      open={openAttachment}
      onOpenChange={setOpenAttachment}
      forceRender
    >
      <Attachments
        ref={attachmentsRef}
        beforeUpload={() => false}
        items={attachmentItems}
        onChange={({ fileList }) => setAttachmentItems(fileList)}
        placeholder={(type) =>
          type === "drop"
            ? {
                title: "拖拽文件到这里",
              }
            : {
                icon: <CloudUploadOutlined />,
                title: "文件列表",
                description: "点击或者拖拽文件到这里上传",
              }
        }
        getDropContainer={() => senderRef.current?.nativeElement}
      />
    </Sender.Header>
  );

  // 底部组件
  const BubbleFooter = (props: { content: string; query: string }) => {
    const handleCopy = () => {
      navigator.clipboard.writeText(props.content);
      message.success("复制成功");
    };

    const handleGenerateApp = () => {
      // todo 生成应用
      // message.info("正在开发中，敬请期待...");
      setMessages((arr) => {
        return [
          ...arr,
          {
            id: arr.length + "",
            content: <GenerateBubble />,
            status: "done",
            role: "assistant",
          },
        ];
      })
    };

    return (
      <Space>
        <Button type="default" onClick={handleGenerateApp}>
          去生成应用
        </Button>
        <span className="text-[#1890ff]">
          你可以继续对上述功能进行修改，点击【去生成应用】即可创建应用
        </span>
      </Space>
    );
  };

  // 提交消息
  const submitMessage = (msg: string) => {
    setSenderVal("");

    setMessages((arr) => {
      const index = arr.length;
      return [
        ...arr,
        { id: index + "", content: msg, status: "done", role: "user" },
        {
          id: index + 1 + "",
          content: "",
          status: "loading",
          role: "assistant",
          loading: true,
        },
      ];
    });
    onRequest(msg);
  };

  // 点击提示词
  const handlePromptItem = (item: any) => {
    const msg = item.data.description || item.data.label;
    const index = messages.length;
    setMessages([
      ...messages,
      { id: index + "", content: msg, status: "done", role: "user" },
      {
        id: index + 1 + "",
        content: "",
        status: "loading",
        role: "assistant",
        loading: true,
      },
    ]);
    onRequest(msg);
  };

  // 停止对话
  const handleStop = () => {
    cancel();
    setMessages((messages) => {
      const arr = [...messages];
      arr[messages.length - 1].status = "stop";
      arr[messages.length - 1].loading = false;
      arr[messages.length - 1].footer = (
        <div>
          <div className="text-12px text-text-secondary pl-12px">
            (已停止思考)
          </div>
          {/* <BubbleFooter
            content={arr[messages.length - 1].content as string}
            query={arr[messages.length - 2].content as string}
          /> */}
        </div>
      );
      return arr;
    });
  };

  return (
    <>
      <div
        className="w-[100vw] h-[100vh] overflow-hidden box-border p-12px pt-30px relative"
        style={{
          backgroundImage: "linear-gradient(137deg, #e5f4ff 0%, #efe7ff 100%)",
        }}
      >
        <XProvider direction="ltr">
          <Flex
            style={{ height: "100%", maxWidth: 1200, margin: "0 auto" }}
            gap={12}
          >
            <Flex
              vertical
              style={{ flex: 1, overflow: "hidden", height: "100%" }}
              gap={8}
            >
              <div
                className="flex-1 overflow-hidden"
                ref={contentRef}
                style={{ height: contentHeight }}
              >
                {!messages.length ? (
                  <>
                    <div className="mt-20 mb-10 flex items-center justify-center">
                      <div className="w-50px">
                        <svg className="icon h-32px w-32px" aria-hidden="true">
                          <use xlinkHref="#icon-AI1"></use>
                        </svg>
                      </div>
                      <div>
                        <div className="ai-title">你好,我是易码工坊AI助手</div>
                        <div className="text-18px text-#666">
                          说出你的需求，我可以帮你快速生成应用~
                        </div>
                      </div>
                    </div>

                    <Prompts
                      // title={"✨ 你可以这样问我:"}
                      items={[
                        {
                          key: "1",
                          icon: <FireOutlined style={{ color: "#FF4D4F" }} />,
                          label: "创建客户管理系统",
                          description: "",
                        },
                        {
                          key: "2",
                          icon: <FireOutlined style={{ color: "#FF4D4F" }} />,
                          label: "创建资产管理系统",
                          description: "",
                        },
                        {
                          key: "3",
                          icon: <FireOutlined style={{ color: "#FF4D4F" }} />,
                          label: "创建项目管理系统",
                          description: "",
                        },
                        {
                          key: "4",
                          icon: <FireOutlined style={{ color: "#FF4D4F" }} />,
                          label: "创建OA办公自动化管理系统",
                          description: "",
                        },
                      ]}
                      onItemClick={handlePromptItem}
                      wrap
                      styles={{
                        item: {
                          flex: "none",
                          width: "calc(50% - 6px)",
                        },
                      }}
                    />
                  </>
                ) : (
                  <Bubble.List
                    ref={listRef}
                    style={{ maxHeight: contentHeight, padding: "0 20px" }}
                    autoScroll
                    roles={roles}
                    items={messages}
                  />
                )}
              </div>
              <div className="flex items-end">
                <div className="w-60px pb-8px shrink-0">
                  <Tooltip title="清空对话">
                    <Button
                      shape="circle"
                      size="large"
                      icon={<ClearOutlined />}
                      onClick={() => {
                        addConversation();
                      }}
                    />
                  </Tooltip>
                </div>
                <div className="flex-1">
                  <Suggestion
                    items={[
                      { label: "创建客户管理系统", value: "report" },
                      { label: "创建资产管理系统", value: "report" },
                      { label: "创建客户管理系统", value: "report" },
                      { label: "创建客户管理系统", value: "report" },
                    ]}
                    onSelect={submitMessage}
                    className="relative overflow-hidden"
                  >
                    {({ onTrigger, onKeyDown }) => {
                      return (
                        <>
                          <div className="sender-wrapper" />
                          <div className="w-full p-1px">
                            <Sender
                              submitType="shiftEnter"
                              ref={senderRef}
                              header={senderHeader}
                              prefix={
                                <Button
                                  type="text"
                                  icon={<LinkOutlined />}
                                  onClick={() => {
                                    setOpenAttachment(!openAttachment);
                                  }}
                                />
                              }
                              value={senderVal}
                              onPasteFile={(file) => {
                                attachmentsRef.current?.upload(file);
                                setOpenAttachment(true);
                              }}
                              onChange={(nextVal) => {
                                if (nextVal === "/") {
                                  onTrigger();
                                } else if (!nextVal) {
                                  onTrigger(false);
                                }
                                setSenderVal(nextVal);
                              }}
                              onKeyDown={onKeyDown}
                              placeholder="请输入应用名称以及需求描述"
                              onSubmit={submitMessage}
                              onCancel={handleStop}
                              actions={(_, info) => {
                                const { SendButton, LoadingButton } =
                                  info.components;

                                return (
                                  <Space size="small">
                                    <Typography.Text type="secondary">
                                      <small>`Shift + Enter`提交</small>
                                    </Typography.Text>
                                    {loading ? (
                                      <LoadingButton type="default" disabled />
                                    ) : (
                                      <SendButton
                                        type="primary"
                                        disabled={false}
                                      />
                                    )}
                                  </Space>
                                );
                              }}
                            />
                          </div>
                        </>
                      );
                    }}
                  </Suggestion>
                </div>
              </div>
            </Flex>
          </Flex>
        </XProvider>
      </div>
    </>
  );
};
