import {
  Bubble,
  Conversations,
  Prompts,
  Sender,
  Suggestion,
  XProvider,
  Welcome,
  Attachments,
  AttachmentsProps,
} from "@ant-design/x";
import { Conversation } from "@ant-design/x/lib/conversations";
import { useChat } from "@/hooks/useChat";

import {
  Card,
  Divider,
  Flex,
  message,
  Button,
  Space,
  Spin,
  Typography,
  Modal,
  Input,
} from "antd";
import { useEffect, useRef, useState } from "react";
import {
  BulbOutlined,
  SmileOutlined,
  UserOutlined,
  EditOutlined,
  DeleteOutlined,
  PlusOutlined,
  CloudUploadOutlined,
  LinkOutlined,
  CopyOutlined,
  RedoOutlined,
  ReadOutlined,
} from "@ant-design/icons";
import type { GetProp, GetRef } from "antd";
import type { ConversationsProps } from "@ant-design/x";
import type { AgentItem } from "./data";
import MarkdownViewer from "@/components/ai/MarkdownViewer";
import { ChangeSessionName, DeleteSession } from "@/api/ai";

type AssistantProps = {
  agent?: AgentItem;
};

// bubbles角色配置
const roles: GetProp<typeof Bubble.List, "roles"> = {
  assistant: {
    placement: "start",
    avatar: {
      icon: <i className="iconfont icon-AI1" />,
      style: { background: "#fde3cf" },
    },
    // typing: { step: 5, interval: 20 },
    loadingRender: () => (
      <Space>
        <Spin size="small" />
        思考中...
      </Space>
    ),
    messageRender: (content) => {
      return typeof content === "string" ? (
        <Typography>
          <MarkdownViewer content={content} />
        </Typography>
      ) : (
        content
      );
    },
    header: "易码工坊AI助手",
  },
  user: {
    placement: "end",
    avatar: { icon: <UserOutlined />, style: { background: "#87d068" } },
  },
};

export default (props: AssistantProps) => {
  const [senderVal, setSenderVal] = useState("");
  const {
    messages,
    setMessages,
    activeConversation,
    changeConversation,
    conversationList,
    onRequest,
    cancel,
    loading,
    loadingSession,
    addConversation,
    setConversationList,
  } = useChat({
    app_name: props.agent?.key || "",
    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;
      });
    },
    onUpdate: (msg) => {
      setMessages((messages) => {
        const arr = [...messages];
        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 handleChangeConversationName = (conversation: Conversation) => {
    let new_name: string;
    Modal.info({
      title: "修改对话名称",
      okText: "提交",
      closable: true,
      content: (
        <div>
          <Input
            type="text"
            defaultValue={conversation.label + ""}
            onChange={(e) => {
              new_name = e.target.value;
            }}
          />
        </div>
      ),
      onOk: () => {
        return ChangeSessionName({
          app_name: props.agent?.key || "",
          session_id: conversation.key,
          new_name,
        }).then(() => {
          message.success("修改成功");
          setConversationList((list) =>
            list?.map((item) =>
              item.key === conversation.key
                ? { ...item, label: new_name }
                : item
            )
          );
        });
      },
    });
  };

  const handleDeleteConversation = (conversation: Conversation) => {
    Modal.confirm({
      title: "删除对话",
      content: "是否删除对话？",
      okText: "删除",
      cancelText: "取消",
      onOk: () => {
        return DeleteSession({
          app_name: props.agent?.key || "",
          session_id: conversation.key,
        }).then(() => {
          message.success("删除成功");
          setConversationList((list) =>
            list?.filter((item) => item.key !== conversation.key)
          );

          addConversation();
        });
      },
    });
  };

  const menuConfig: ConversationsProps["menu"] = (conversation) => {
    if (conversation.key === "1") return undefined;
    return {
      items: [
        {
          label: "修改对话名称",
          key: "edit",
          icon: <EditOutlined />,
        },
        {
          label: "删除对话",
          key: "del",
          icon: <DeleteOutlined />,
          danger: true,
        },
      ],
      onClick: (menuInfo) => {
        // 修改对话名称
        if (menuInfo.key === "edit") {
          handleChangeConversationName(conversation);
        }
        // 删除对话
        if (menuInfo.key === "del") {
          handleDeleteConversation(conversation);
        }
      },
    };
  };

  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();
    window.addEventListener("resize", setHeight);
    return () => {
      window.removeEventListener("resize", setHeight);
    };
  }, []);

  // 附件组件
  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 handleRedo = () => {
      submitMessage(props.query);
    };
    return (
      <Space>
        <Button
          type="text"
          size="small"
          icon={<CopyOutlined />}
          onClick={handleCopy}
        >
          复制
        </Button>
        <Button
          type="text"
          size="small"
          icon={<RedoOutlined />}
          onClick={handleRedo}
        >
          重新生成
        </Button>
      </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 (
    <>
      <Card
        className="w-full h-full"
        styles={{
          body: {
            height: "calc(100% - 48px)",
          },
        }}
        title={
          <span className="flex items-center">
            <img
              className="w-20px h-20px rounded-8px"
              src={props.agent?.icon}
            />
            <span className="ml-4px">{props.agent?.name}</span>
          </span>
        }
      >
        <XProvider direction="ltr">
          <Flex style={{ height: "100%" }} gap={12}>
            <Spin spinning={loadingSession}>
              <div className="w-200px">
                <div className="w-full px-12px">
                  <Button
                    type="primary"
                    className="w-full"
                    icon={<PlusOutlined />}
                    onClick={addConversation}
                  >
                    新对话
                  </Button>
                </div>
                <Conversations
                  style={{ width: 200 }}
                  activeKey={activeConversation}
                  onActiveChange={changeConversation}
                  menu={menuConfig}
                  items={conversationList}
                />
              </div>
            </Spin>
            <Divider type="vertical" style={{ height: "100%" }} />
            <Flex vertical style={{ flex: 1 }} gap={8}>
              <div
                className="flex-1"
                ref={contentRef}
                style={{ height: contentHeight }}
              >
                {!messages.length ? (
                  <>
                    <div className="mt-20 mb-10">
                      <Welcome
                        icon={
                          <img
                            src={props.agent?.icon}
                            className="rounded-8px"
                          />
                        }
                        title={`你好！我是易码工坊${props.agent?.name || "AI"}助手`}
                        description={props.agent?.description}
                      />
                    </div>

                    <Prompts
                      title={
                        props.agent?.promptsItems ? "✨ 你可以这样问我:" : ""
                      }
                      items={props.agent?.promptsItems || []}
                      wrap
                      onItemClick={handlePromptItem}
                    />
                  </>
                ) : (
                  <Bubble.List
                    style={{ maxHeight: contentHeight }}
                    autoScroll
                    roles={roles}
                    items={messages}
                  />
                )}
              </div>
              <Prompts
                items={[
                  {
                    key: "1",
                    icon: <BulbOutlined style={{ color: "#FFD700" }} />,
                    label: "写需求",
                  },
                  {
                    key: "2",
                    icon: <SmileOutlined style={{ color: "#52C41A" }} />,
                    label: "生成代码",
                  },
                  {
                    key: "3",
                    icon: <ReadOutlined style={{ color: "#52C41A" }} />,
                    label: "问题解答",
                  },
                ]}
                onItemClick={handlePromptItem}
              />

              <Suggestion
                items={[{ label: "写一个应用介绍", value: "report" }]}
                onSelect={submitMessage}
              >
                {({ onTrigger, onKeyDown }) => {
                  return (
                    <Sender
                      ref={senderRef}
                      header={senderHeader}
                      loading={loading}
                      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}
                    />
                  );
                }}
              </Suggestion>
            </Flex>
          </Flex>
        </XProvider>
      </Card>
    </>
  );
};
