import React, { useEffect, useRef, useState } from 'react';
import { Button, GetProp, GetRef, Popover, Space, Spin, Tooltip, message } from 'antd';
import {
    CloseOutlined,
    CloudUploadOutlined,
    CommentOutlined,
    OpenAIFilled,
    PlusOutlined,
    RedoOutlined,
    UserOutlined,
    PaperClipOutlined
} from '@ant-design/icons';
import {
    Attachments,
    type AttachmentsProps,
    Bubble,
    Conversations,
    Sender,
    Suggestion,
    useXAgent,
    useXChat,
} from '@ant-design/x';
import Welcome from './welcome';
import type { Conversation } from '@ant-design/x/es/conversations';
import { createStyles } from 'antd-style';
import dayjs from 'dayjs';
import ReactMarkdown from 'react-markdown';
import avatarSrc from '@/assets/public/logo.png';

const useWorkareaStyle = createStyles(({ token, css }) => {
    return {
        copilotWrapper: css`
      height: 100%;
      display: flex;
    `,
        workarea: css`
      flex: 1;
      background: ${token.colorBgLayout};
      display: flex;
      flex-direction: column;
    `,
        workareaHeader: css`
      box-sizing: border-box;
      height: 52px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0 48px 0 28px;
      border-bottom: 1px solid ${token.colorBorder};
    `,
        headerTitle: css`
      font-weight: 600;
      font-size: 15px;
      color: ${token.colorText};
      display: flex;
      align-items: center;
      gap: 8px;
    `,
        headerButton: css`
      background-image: linear-gradient(78deg, #8054f2 7%, #3895da 95%);
      border-radius: 12px;
      height: 24px;
      width: 93px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
      cursor: pointer;
      font-size: 12px;
      font-weight: 600;
      transition: all 0.3s;
      &:hover {
        opacity: 0.8;
      }
    `,
        workareaBody: css`
      flex: 1;
      padding: 16px;
      background: ${token.colorBgContainer};
      border-radius: 16px;
      min-height: 0;
    `,
        bodyContent: css`
      overflow: auto;
      height: 100%;
      padding-right: 10px;
    `,
        bodyText: css`
      color: ${token.colorText};
      padding: 8px;
    `,
    };
});
// createStyles 返回一个 hook，使用 design token 生成样式对象
const useCopilotStyle = createStyles(({ token, css }) => {
    return {
        copilotChat: css`
      display: flex;
      flex-direction: column;
      background: ${token.colorBgContainer};
      color: ${token.colorText};
    `,
        // chatHeader 样式
        chatHeader: css`
      height: 52px;
      box-sizing: border-box;
      border-bottom: 1px solid ${token.colorBorder};
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0 10px 0 16px;
    `,
        headerTitle: css`
      font-weight: 600;
      font-size: 15px;
    `,
        headerButton: css`
      font-size: 18px;
    `,
        conversations: css`
      width: 300px;
      .ant-conversations-list {
        padding-inline-start: 0;
      }
    `,
        // chatList 样式
        chatList: css`
      overflow: auto;
      padding-block: 16px;
      flex: 1;
    `,
        chatWelcome: css`
      margin-inline: 16px;
      padding: 12px 16px;
      border-radius: 2px 12px 12px 12px;
      background: ${token.colorBgTextHover};
      margin-bottom: 16px;
    `,
        loadingMessage: css`
      background-image: linear-gradient(90deg, #ff6b23 0%, #af3cb8 31%, #53b6ff 89%);
      background-size: 100% 2px;
      background-repeat: no-repeat;
      background-position: bottom;
    `,
        // chatSend 样式
        chatSend: css`
      padding: 12px;
    `,
        sendAction: css`
      display: flex;
      align-items: center;
      margin-bottom: 12px;
      gap: 8px;
    `,
        speechButton: css`
      font-size: 18px;
      color: ${token.colorText} !important;
    `,
    };
});
// 消息气泡的数据类型：
// - role: 消息的角色，通常为 'user' 或 'assistant'
// - content: 文本内容（可能包含 markdown）
type BubbleDataType = {
    role: string;
    content: string;
};

// MOCK_SESSION_LIST: 用于展示会话历史（仅示例/初始占位）
const MOCK_SESSION_LIST = [
    {
        key: '5',
        label: 'New session',
        group: 'Today',
    },
    {
        key: '4',
        label: 'What has Ant Design X upgraded?',
        group: 'Today',
    },
    {
        key: '3',
        label: 'New AGI Hybrid Interface',
        group: 'Today',
    },
    {
        key: '2',
        label: 'How to quickly install and import components?',
        group: 'Yesterday',
    },
    {
        key: '1',
        label: 'What is Ant Design X?',
        group: 'Yesterday',
    },
];

// MOCK_SUGGESTIONS: Suggestion 组件的数据来源
// 用于输入框的快速建议/模板，可包含子菜单和图标
const MOCK_SUGGESTIONS = [
    { label: 'Write a report', value: 'report' },
    { label: 'Draw a picture', value: 'draw' },
    {
        label: 'Check some knowledge',
        value: 'knowledge',
        icon: <OpenAIFilled />,
        children: [
            { label: 'About React', value: 'react' },
            { label: 'About Ant Design', value: 'antd' },
        ],
    },
];

// 生成中占位文本
const AGENT_PLACEHOLDER = 'Generating content, please wait...';

// CopilotProps: 组件传入的参数
// - copilotOpen: 控制 Copilot 是否可见
// - setCopilotOpen: 切换 Copilot 可见性的回调
// - appId: 当前应用/会话的上下文 ID，会传给后端
interface CopilotProps {
    copilotOpen: boolean;
    setCopilotOpen: (open: boolean) => void;
    appId: string,
    infoDetail: any;
    saveConfig: () => Promise<boolean>;
}

const Copilot = (props: CopilotProps) => {
    const { copilotOpen, setCopilotOpen, infoDetail,saveConfig } = props;
    const { styles } = useCopilotStyle();

    // Attachments 组件的引用，用于编程式上传文件
    const attachmentsRef = useRef<GetRef<typeof Attachments>>(null);
    // 保存当前请求对应的 AbortController，方便取消请求
    const abortController = useRef<AbortController | null>(null);

    // ==================== State ====================

    const [messageHistory, setMessageHistory] = useState<Record<string, any>>({});

    const [sessionList, setSessionList] = useState<Conversation[]>(MOCK_SESSION_LIST);
    const [curSession, setCurSession] = useState(sessionList[0].key);

    const [attachmentsOpen, setAttachmentsOpen] = useState(false);
    const [files, setFiles] = useState<GetProp<AttachmentsProps, 'items'>>([]);

    const [inputValue, setInputValue] = useState('');

    // useXAgent 用于创建一个可复用的请求代理(agent)
    // 可以在这里统一传入 baseURL、headers（比如 Authorization: Bearer <token>）
    // 例如：useXAgent({ baseURL, headers: { Authorization: `Bearer ${token}` } })
    const [agent] = useXAgent<BubbleDataType>({
        // baseURL: props.appId?'/api/deepseek/api/chat':'/api/deepseek/api/preChat',
        baseURL: '/api/deepseek/api/preChat',
    });

    // loading 表示 agent 是否正在进行请求
    const loading = agent.isRequesting();

    // useXChat 管理流式消息和请求生命周期：
    // - messages: 当前要渲染的消息数组
    // - onRequest: 发起一次对话请求的函数（会返回/管理流式更新）
    // - setMessages: 可手动替换消息数组（比如清空或恢复历史）
    const { messages, onRequest, setMessages } = useXChat({
        agent,
        // requestFallback：当请求失败或被取消时，提供回退消息
        requestFallback: (_, { error }) => {
            if (error.name === 'AbortError') {
                return {
                    content: 'Request is aborted',
                    role: 'assistant',
                };
            }
            return {
                content: 'Request failed, please try again!',
                role: 'assistant',
            };
        },
        // transformMessage：将后端返回的分片/原始格式转换为 UI 可渲染的消息对象
        transformMessage: (info) => {
            // console.log(info, '回复消息');

            const { originMessage, chunk } = info || {};

            let currentContent = '';

            try {
                if (chunk?.data) {
                    const message = JSON.parse(chunk?.data);
                    // message.event 用于判断是否结束分片
                    if (message.event !== 'finish') {
                        currentContent = message?.data || '';
                    }
                }
            } catch (error) {
                console.error(error);
            }

            const content = `${originMessage?.content || ''}${currentContent}`;

            return {
                content: content,
                role: 'assistant',
            };

        },
        // expose 内部的 AbortController，方便外部取消请求
        resolveAbortController: (controller) => {
            abortController.current = controller;
        },
    });

    // ==================== Event ====================

    // 用户提交消息：把消息内容传给 onRequest 发起对话请求
    // 可在这里传入 headers（如 token）作为单次请求的鉴权方式
    const handleUserSubmit = (val: string,infoDetail?:any) => {
        // console.log('User submitted:', val);
        // if(props.appId){
        //     onRequest({
        //         message: { content: val, role: 'user' },
        //         appId: props.appId,
        //         // 可选扩展字段示例：
        //         // headers: { Authorization: `Bearer ${token}` },
        //         request_id: undefined,
        //         returnType: undefined,
        //         knowledge_ids: undefined,
        //         document_ids: undefined
        //     });
        // }else{
            onRequest({
                message: { content: val, role: 'user' },
                // appId: props.appId,
                // 可选扩展字段示例：
                // headers: { Authorization: `Bearer ${token}` },
                jkApplicationParams:infoDetail,
                request_id: undefined,
                returnType: undefined,
                knowledge_ids: undefined,
                document_ids: undefined
            });
        // }

        // 如果当前会话为 New session，则用用户第一条消息作为会话标题示例
        if (sessionList.find((i) => i.key === curSession)?.label === 'New session') {
            setSessionList(
                sessionList.map((i) => (i.key !== curSession ? i : { ...i, label: val?.slice(0, 20) })),
            );
        }
    };

    // 处理粘贴文件（从剪贴板粘贴文件）
    // 将 FileList 转为数组再上传，兼容不同的 TS 设置
    const onPasteFile = (_: File, files: FileList) => {
        Array.from(files).forEach((file) => {
            attachmentsRef.current?.upload(file as File);
        });
        setAttachmentsOpen(true);
    };

    // ==================== Nodes ====================
    const chatHeader = (
        <div className={styles.chatHeader}>
            <div className={styles.headerTitle}>✨ AI Copilot</div>
            <Space size={0}>
                <Button
                    type="text"
                    icon={<PlusOutlined />}
                    onClick={() => {
                        if (agent.isRequesting()) {
                            message.error(
                                'Message is Requesting, you can create a new conversation after request done or abort it right now...',
                            );
                            return;
                        }

                        if (messages?.length) {
                            const timeNow = dayjs().valueOf().toString();
                            abortController.current?.abort();
                            // The abort execution will trigger an asynchronous requestFallback, which may lead to timing issues.
                            // In future versions, the sessionId capability will be added to resolve this problem.
                            setTimeout(() => {
                                setSessionList([
                                    { key: timeNow, label: 'New session', group: 'Today' },
                                    ...sessionList,
                                ]);
                                setCurSession(timeNow);
                                setMessages([]);
                            }, 100);
                        } else {
                            message.error('It is now a new conversation.');
                        }
                    }}
                    className={styles.headerButton}
                />
                <Popover
                    placement="bottom"
                    styles={{ body: { padding: 0, maxHeight: 600 } }}
                    content={
                        <Conversations
                            items={sessionList?.map((i) =>
                                i.key === curSession ? { ...i, label: `[current] ${i.label}` } : i,
                            )}
                            activeKey={curSession}
                            groupable
                            onActiveChange={async (val) => {
                                abortController.current?.abort();
                                // The abort execution will trigger an asynchronous requestFallback, which may lead to timing issues.
                                // In future versions, the sessionId capability will be added to resolve this problem.
                                setTimeout(() => {
                                    setCurSession(val);
                                    setMessages(messageHistory?.[val] || []);
                                }, 100);
                            }}
                            styles={{ item: { padding: '0 8px' } }}
                            className={styles.conversations}
                        />
                    }
                >
                    <Button type="text" icon={<CommentOutlined />} className={styles.headerButton} />
                </Popover>
                <Button
                    type="text"
                    icon={<CloseOutlined />}
                    onClick={() => setCopilotOpen(false)}
                    className={styles.headerButton}
                />
            </Space>
        </div>
    );
    const chatList = (
        <div className={styles.chatList}>
            {messages?.length ? (
                /** 消息列表 */
                <Bubble.List
                    style={{ height: '100%', paddingInline: 16 }}
                    items={messages?.map((i) => ({
                        ...i.message,
                        classNames: {
                            content: i.status === 'loading' ? styles.loadingMessage : '',
                        },
                        typing: i.status === 'loading' ? { step: 5, interval: 20, suffix: <>💗</> } : false,
                        content: <ReactMarkdown>{i.message.content}</ReactMarkdown>,
                        avatar: i.message.role !== 'user' ? <img style={{ width: 30, height: 30 }} src={avatarSrc} /> : <UserOutlined style={{ fontSize: 24, color: '#1890ff' }} />,
                    }))}
                    roles={{
                        assistant: {
                            placement: 'start',
                            // footer: (
                            //     <div style={{ display: 'flex' }}>
                            //         <Button type="text" size="small" icon={<ReloadOutlined />} />
                            //         <Button type="text" size="small" icon={<CopyOutlined />} />
                            //         <Button type="text" size="small" icon={<LikeOutlined />} />
                            //         <Button type="text" size="small" icon={<DislikeOutlined />} />
                            //     </div>
                            // ),
                            loadingRender: () => (
                                <Space>
                                    <Spin size="small" />
                                    {AGENT_PLACEHOLDER}
                                </Space>
                            ),
                        },
                        user: { placement: 'end' },
                    }}
                />
            ) : (
                /** 没有消息时的 welcome */
                // <Welcome
                //     variant="borderless"
                //     title="预览调试"
                //     description="请输入问题进行预览调试"
                //     className={styles.chatWelcome}
                // />
                <Welcome infoDetail={infoDetail} saveConfig={saveConfig} handleUserSubmit={handleUserSubmit}></Welcome>
            )}
        </div>
    );
    const sendHeader = (
        <Sender.Header
            title="Upload File"
            styles={{ content: { padding: 0 } }}
            open={attachmentsOpen}
            onOpenChange={setAttachmentsOpen}
            forceRender
        >
            <Attachments
                ref={attachmentsRef}
                beforeUpload={() => false}
                items={files}
                onChange={({ fileList }) => setFiles(fileList)}
                placeholder={(type) =>
                    type === 'drop'
                        ? { title: 'Drop file here' }
                        : {
                            icon: <CloudUploadOutlined />,
                            title: 'Upload files',
                            description: 'Click or drag files to this area to upload',
                        }
                }
            />
        </Sender.Header>
    );
    const chatSender = (
        <div className={styles.chatSend}>
            {/** 输入框 */}
            <Suggestion items={MOCK_SUGGESTIONS} onSelect={(itemVal) => setInputValue(`[${itemVal}]:`)}>
                {({ onTrigger, onKeyDown }) => (
                    <Sender
                        loading={loading}
                        value={inputValue}
                        onChange={(v) => {
                            onTrigger(v === '/');
                            setInputValue(v);
                        }}
                        onSubmit={ async() => {
                             const result = await saveConfig();
                            if(result){
                                handleUserSubmit(inputValue,result);
                                setInputValue('');
                            }
                        }}
                        onCancel={() => {
                            abortController.current?.abort();
                        }}
                        allowSpeech={true}
                        placeholder="请输入"
                        onKeyDown={onKeyDown}
                        header={sendHeader}
                        prefix={
                            <img style={{ width: 30, height: 30 }} src={avatarSrc} />
                            // <Button
                            //     type="text"
                            //     icon={<PaperClipOutlined style={{ fontSize: 18 }} />}
                            //     onClick={() => setAttachmentsOpen(!attachmentsOpen)}
                            // />
                        }
                        onPasteFile={onPasteFile}
                        actions={(_, info) => {
                            const { SendButton, LoadingButton, SpeechButton, ClearButton } = info.components;
                            return (
                                <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                                    <SpeechButton className={styles.speechButton} />
                                    <Tooltip title={loading ? '停止' : '发送'}>
                                        {loading ? <LoadingButton type="default" /> : <SendButton type="primary" />}
                                    </Tooltip>
                                    <Tooltip title="重新开始">
                                        <Button
                                            type="primary"
                                            shape="circle"
                                            icon={<RedoOutlined />}
                                            onClick={() => {
                                                const timeNow = dayjs().valueOf().toString();
                                                abortController.current?.abort();

                                                // 确保异步操作完成后清空消息
                                                setTimeout(() => {
                                                    setSessionList([
                                                        { key: timeNow, label: 'New session', group: 'Today' },
                                                        ...sessionList,
                                                    ]);
                                                    setCurSession(timeNow);
                                                    setMessages([]);
                                                }, 100);
                                            }}
                                        />
                                    </Tooltip>
                                </div>
                            );
                        }}
                    />
                )}
            </Suggestion>
        </div>
    );

    useEffect(() => {
        // history mock
        if (messages?.length) {
            setMessageHistory((prev) => ({
                ...prev,
                [curSession]: messages,
            }));
        }
    }, [messages]);

    return (
        <div className={styles.copilotChat} style={{ width: copilotOpen ? '100%' : 0 }}>
            {/** 对话区 - header */}
            {/* {chatHeader} */}
            {/** 对话区 - 消息列表 */}
            {chatList}
            {/** 对话区 - 输入框 */}
            {chatSender}
        </div>
    );
};


const Chat: React.FC<{ appId: string,infoDetail?: any,saveConfig: () => Promise<any> }> = (props) => {
    const { styles: workareaStyles } = useWorkareaStyle();
    const [copilotOpen, setCopilotOpen] = useState(true);
    const { infoDetail } = props;  
    return (
        <div className={workareaStyles.copilotWrapper}>
            <Copilot
                copilotOpen={copilotOpen}
                infoDetail={infoDetail}
                setCopilotOpen={setCopilotOpen}
                appId={props.appId}
                saveConfig={props.saveConfig}
            />
        </div>
    );
};

export default Chat;