import { ChatEventType, RoleType } from "@coze/api";
import {
  EventNames,
  RealtimeAPIError,
  RealtimeClient,
  RealtimeError,
  RealtimeUtils,
} from "@coze/realtime-api";
import {
  createContext,
  ReactNode,
  useCallback,
  useContext,
  useRef,
  useState,
} from "react";
import { useToast } from "@/hooks/use-toast";

type RoomInfo = {
  appId: string;
  roomId: string;
  token: string;
  uid: string;
};

export type FileInfo = {type:string,url:string,tableName:string,provinceName:string,subjectClaim:string}

export const RealtimeClientContext = createContext<{
  client: RealtimeClient | null;
  isConnecting: boolean;
  isConnected: boolean;
  audioEnabled: boolean;
  isSupportVideo: boolean;
  messageList: { content: string; role: RoleType }[];
  isAiTalking: boolean;
  roomInfo: RoomInfo | null;

  initClient: ({
    initMessage,
    fileInfo,
  }: {
    initMessage?: string;
    fileInfo?: FileInfo;
  }) => void;
  handleConnect: ({
    initMessage,
    fileInfo,
  }: {
    initMessage?: string;
    fileInfo?: FileInfo;
  }) => Promise<void>;
  handleInterrupt: () => void;
  handleDisconnect: () => void;
  toggleMicrophone: () => void;
}>({
  client: null,
  isConnecting: false,
  isConnected: false,
  audioEnabled: true,
  isSupportVideo: false,
  messageList: [],
  isAiTalking: false,
  roomInfo: null,

  initClient: () => {},
  handleConnect: () => Promise.resolve(),
  handleInterrupt: () => {},
  handleDisconnect: () => {},
  toggleMicrophone: () => {},
});

// 添加自定义hook
export const useRealtimeClient = () => {
  const context = useContext(RealtimeClientContext);

  if (context === undefined) {
    throw new Error("useRealtimeClient必须在RealtimeClientProvider内部使用");
  }

  return { ...context };
};

export const RealtimeClientProvider = ({
  children,
}: {
  children: ReactNode;
}) => {
  const token = import.meta.env.VITE_COZE_TOKEN;
  const botId = import.meta.env.VITE_COZE_BOT_ID;
  const voiceId = import.meta.env.VITE_COZE_VOICE_ID;
  const connectorId = "1024";

  const clientRef = useRef<RealtimeClient | null>(null);
  // 添加连接锁
  const connectingLockRef = useRef<boolean>(false);
  // 实时语音回复消息列表
  const [messageList, setMessageList] = useState<
    { content: string; role: RoleType; event?: any }[]
  >([]);
  // 是否正在连接
  const [isConnecting, setIsConnecting] = useState(false);
  // 是否已连接
  const [isConnected, setIsConnected] = useState(false);
  // 是否开启麦克风
  const [audioEnabled, setAudioEnabled] = useState(true);
  // 是否支持视频
  const [isSupportVideo] = useState(false);
  // 是否正在说话
  const [isAiTalking, setIsAiTalking] = useState(false);

  const [roomInfo, setRoomInfo] = useState<RoomInfo | null>(null);

  // 记录文件解析是否完成 分为 没有解析 -1，未解析 0，解析中 1，解析完成 2

  const fileParseStatusRef = useRef(-1);

  const { toast } = useToast();

  const initClient = async ({
    initMessage,
    fileInfo,
  }: {
    initMessage?: string;
    fileInfo?: FileInfo;
  }) => {
    const permission = await RealtimeUtils.checkDevicePermission(false);
    const device = await RealtimeUtils.getAudioDevices();

    if (!permission.audio) {
      toast({
        title: "连接错误",
        description: "需要麦克风访问权限",
      });
      throw new Error("需要麦克风访问权限");
    }

    if (device.audioInputs.length === 0) {
      toast({
        title: "连接错误",
        description: "没有麦克风设备",
      });
      throw new Error("没有麦克风设备");
    }

    const client = new RealtimeClient({
      accessToken: token,
      botId: botId,
      voiceId: voiceId,
      connectorId: connectorId,
      allowPersonalAccessTokenInBrowser: true, // 可选：允许在浏览器中使用个人访问令牌
      suppressStationaryNoise: true,
      suppressNonStationaryNoise: true,
      debug: false,
    });

    clientRef.current = client;

    setupEventListeners(client);
    setupMessageEventListeners(client, { initMessage, fileInfo });
    setupInitMessageEventListener(client, { initMessage, fileInfo });
  };

  const handleConnect = async ({
    initMessage,
    fileInfo,
  }: {
    initMessage?: string;
    fileInfo?: FileInfo;
  }) => {
    try {
      // 使用连接锁确保原子性
      if (connectingLockRef.current) {
        return;
      }
      connectingLockRef.current = true;

      // 如果已经连接或正在连接中，直接返回
      if (isConnected || isConnecting) {
        connectingLockRef.current = false;
        return;
      }

      if (!clientRef.current) {
        await initClient({ initMessage, fileInfo });
      }
      await clientRef.current?.connect();
      await clientRef.current?.setAudioEnable(false);
      setAudioEnabled(false);
      
    } catch (error) {
      // console.error(error);
      if (error instanceof RealtimeAPIError) {
        switch (error.code) {
          case RealtimeError.CREATE_ROOM_ERROR:
            console.error(`创建房间失败: ${error.message}`);
            break;
          case RealtimeError.CONNECTION_ERROR:
            console.error(`加入房间失败: ${error.message}`);
            break;
          case RealtimeError.DEVICE_ACCESS_ERROR:
            console.error(`获取设备失败: ${error.message}`);
            break;
          default:
            console.error(`连接错误: ${error.message}`);
        }
      } else {
        console.error("连接错误：" + error);
      }
    } finally {
      // 确保在任何情况下都释放连接锁
      connectingLockRef.current = false;
    }
  };

  const handleInterrupt = () => {
    try {
      clientRef.current?.interrupt();
    } catch (error) {
      console.error("打断失败：" + error);
    }
  };

  const handleDisconnect = async () => {
    try {
      // 关闭客户的时候清除一些信息
      setIsAiTalking(false);
      setMessageList([]);
      await clientRef.current?.setAudioEnable(false);
      setAudioEnabled(false);

      await clientRef.current?.disconnect();
      clientRef.current?.clearEventHandlers();
      clientRef.current = null;
      setIsConnected(false);
    } catch (error) {
      console.error("断开失败：" + error);
    }
  };

  const toggleMicrophone = async () => {
    try {
      await clientRef.current?.setAudioEnable(!audioEnabled);
      setAudioEnabled(!audioEnabled);
    } catch (error) {
      console.error("切换麦克风状态失败：" + error);
    }
  };

  const setupInitMessageEventListener = useCallback(
    (
      client: RealtimeClient,
      { initMessage, fileInfo }: { initMessage?: string; fileInfo?: FileInfo }
    ) => {
      client.on(EventNames.ALL_SERVER, async (eventName, _event: any) => {
        if (eventName === "server.session.created") {
          await client.sendMessage({
            id: "",
            event_type: "session.update",
            data: {
              chat_config: {
                allow_voice_interrupt: false,
              },
              turn_detection: {
                silence_duration_ms: 2000,
              },
            },
          });
        }
        if (eventName === "server.bot.join" && initMessage) {
          // 这里需要加个 server. 前缀
          await clientRef.current?.sendMessage({
            id: "",
            event_type: "conversation.message.create",
            data: {
              role: "user",
              content_type: "text",
              content: initMessage,
            },
          });
        } else if (eventName === "server.bot.join" && fileInfo) {
          fileParseStatusRef.current = 0;          

          await clientRef.current?.sendMessage({
            id: "",
            event_type: "conversation.message.create",
            data: {
              role: "user",
              content_type: "object_string",
              content: JSON.stringify([
                {
                  type: "text",
                  text: "帮我解读这个文件,结合当下的专业行情以及对该专业未来的发展趋势,简介的给出志愿建议",
                },
                { type: "image", file_url: fileInfo.url },
              ]),
            },
          });
        }
      });
    },
    [clientRef.current]
  );

  const setupMessageEventListeners = (
    client: RealtimeClient,
    { initMessage, fileInfo }: { initMessage?: string; fileInfo?: FileInfo }
  ) => {
    client.on(EventNames.ALL, (_eventName, event: any) => {
      // AI智能体设置

      if(_eventName === 'server.error'){
        // 长期不活动，服务端终结了
        handleDisconnect();
      }
      

      if (
        event.event_type !== ChatEventType.CONVERSATION_MESSAGE_DELTA &&
        event.event_type !== ChatEventType.CONVERSATION_MESSAGE_COMPLETED &&
        event.event_type !== "conversation.created" &&
        event.event_type !== "conversation.message.create"
      ) {
        return;
      }

      const content = event.data.content;
      if (
        fileParseStatusRef.current === 0 &&
        event.data.type === "function_call" &&
        JSON.parse(content).name === "doc_reader-PDF_reader"
      ) {
        fileParseStatusRef.current = 1;
      } else if (
        event.data.type === "tool_response" &&
        fileParseStatusRef.current === 1
      ) {
        fileParseStatusRef.current = 2;
      }

      setMessageList((prev) => {
        // 如果上一个事件是增量更新，则附加到最后一条消息
        if (
          prev.length > 0 &&
          prev[prev.length - 1].event?.event_type ===
            ChatEventType.CONVERSATION_MESSAGE_DELTA &&
          event.event_type === ChatEventType.CONVERSATION_MESSAGE_DELTA &&
          prev[prev.length - 1].event.data.type === event.data.type &&
          prev[prev.length - 1].event.data.answer_id === event.data.answer_id
        ) {
          return [
            ...prev.slice(0, -1),
            {
              content: prev[prev.length - 1].content + content,
              role: prev[prev.length - 1].role,
              event: event,
            },
          ];
        }

        // 添加AI的欢迎语
        if (
          typeof initMessage === "undefined" &&
          typeof fileInfo === "undefined" &&
          event.event_type === "conversation.created"
        ) {
          return [
            ...prev,
            {
              content: event.data.prologue,
              role: RoleType.Assistant,
              event: event,
            },
          ];
        }

        // 否则添加新消息
        if (
          (content !== "" &&
            event.event_type === ChatEventType.CONVERSATION_MESSAGE_DELTA) ||
          (event.event_type === ChatEventType.CONVERSATION_MESSAGE_COMPLETED &&
            (event.data.type === "answer" || event.data.type === "question") &&
            event.data.role !== RoleType.Assistant)
        ) {
          // lastEvent = event;
          if(event.event_type === ChatEventType.CONVERSATION_MESSAGE_DELTA && fileParseStatusRef.current === 2){            
            fileParseStatusRef.current = -1;
          }
          return [
            ...prev,
            { content: content, role: event.data.role, event: event },
          ];
        }

        // 添加一个文件解析的信息
        if (
          fileParseStatusRef.current === 0 &&
          event.event_type === "conversation.message.completed"
        ) {
          return [
            ...prev,
            {
              content: "AI正在解析您的文档...",
              role: RoleType.Assistant,
              event: event,
              fileParseStatus: fileParseStatusRef.current,
              fileInfo: fileInfo,
            },
          ];
        } else if (
          fileParseStatusRef.current === 1 &&
          event.event_type === "conversation.message.completed"
        ) {
          return [
            ...prev.slice(0, -1),
            {
              content: "AI正在调用插件",
              role: prev[prev.length - 1].role,
              event: event,
              fileParseStatus: fileParseStatusRef.current,
              fileInfo: fileInfo,
            },
          ];
        } else if (
          fileParseStatusRef.current === 2 &&
          event.event_type === "conversation.message.completed"
        ) {                  
          return [
            ...prev.slice(0, -1),
            {
              content: "文档解析完成",
              role: RoleType.Assistant,
              event: event,
              fileParseStatus: fileParseStatusRef.current,
              fileInfo: fileInfo,
            },
          ];
        }
        return prev;
      });
    });
  };

  // 设置事件监听器
  const setupEventListeners = useCallback(
    (client: RealtimeClient) => {
      // 监听 AI 开始说话事件
      client.on(EventNames.AUDIO_AGENT_SPEECH_STARTED, async () => {
        // console.log("AI开始说话");
        setIsAiTalking(true);
        await clientRef.current?.setAudioEnable(false);
        setAudioEnabled(false);
      });

      // 监听 AI 结束说话事件
      client.on(EventNames.AUDIO_AGENT_SPEECH_STOPPED, async () => {
        // console.log("AI结束说话");
        setIsAiTalking(false);
        await clientRef.current?.setAudioEnable(true);
        setAudioEnabled(true);
      });

      // 监听连接客户端
      client.on(EventNames.CONNECTING, () => {
        setIsConnecting(true);
        setIsConnected(false);
      });

      // 客户端连接成功
      client.on(EventNames.CONNECTED, (_eventName: string, event: any) => {
        setRoomInfo(event);
        setIsConnecting(false);
        setIsConnected(true);
      });
      
    },
    [clientRef.current]
  );

  return (
    <RealtimeClientContext.Provider
      value={{
        client: clientRef.current,
        isConnecting,
        isConnected,
        audioEnabled,
        isSupportVideo,
        messageList,
        isAiTalking,
        roomInfo,
        initClient,
        handleConnect,
        handleInterrupt,
        handleDisconnect,
        toggleMicrophone,
      }}
    >
      {children}
    </RealtimeClientContext.Provider>
  );
};
