import { FileUploadProps } from '@/components/file-upload';
import { useHandleFilterSubmit } from '@/components/list-filter-bar/use-handle-filter-submit';
import message from '@/components/ui/message';
import { AgentCategory, AgentGlobals } from '@/constants/agent';
import { useFetchTenantInfo } from '@/hooks/use-user-setting-request';
import {
  AgentListItem,
  IAgentLogResponse,
  IAgentLogsRequest,
  IAgentLogsResponse,
  IBuiltinPipelineListResponse,
  IFlow,
  IFlowTemplate,
  IPipeLineListRequest,
  ITraceData,
  IWebhookTrace,
} from '@/interfaces/database/agent';
import {
  IAgentWebhookTraceRequest,
  IDebugSingleRequestBody,
} from '@/interfaces/request/agent';
import i18n from '@/locales/config';
import { IInputs } from '@/pages/agent/interface';
import { useGetSharedChatSearchParams } from '@/pages/next-chats/hooks/use-send-shared-message';
import agentService, {
  createAgentSession,
  deleteAgentSession,
  fetchAgentLogsByCanvasId,
  fetchAgentLogsById,
  fetchPipeLineList,
  fetchSharedTrace,
  fetchTrace,
  fetchWebhookTrace,
  updateAgent,
  updateAgentTags,
  uploadAgentFile,
} from '@/services/agent-service';
import { buildMessageListWithUuid } from '@/utils/chat';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useDebounce } from 'ahooks';
import { get, isEmpty, set } from 'lodash';
import { useCallback, useState } from 'react';
import { useParams, useSearchParams } from 'react-router';
import {
  useGetPaginationWithRouter,
  useHandleSearchChange,
} from './logic-hooks';

export const enum AgentApiAction {
  FetchAgentListByPage = 'fetchAgentListByPage',
  FetchAllAgentList = 'fetchAllAgentList',
  FetchAgentList = 'fetchAgentList',
  UpdateAgentSetting = 'updateAgentSetting',
  DeleteAgent = 'deleteAgent',
  FetchAgentDetail = 'fetchAgentDetail',
  ResetAgent = 'resetAgent',
  SetAgent = 'setAgent',
  FetchAgentTemplates = 'fetchAgentTemplates',
  UploadAgentFile = 'uploadAgentFile',
  UploadAgentFileWithProgress = 'uploadAgentFileWithProgress',
  Trace = 'trace',
  TestDbConnect = 'testDbConnect',
  DebugSingle = 'debugSingle',
  FetchInputForm = 'fetchInputForm',
  FetchVersionList = 'fetchVersionList',
  FetchVersion = 'fetchVersion',
  FetchExternalAgentInputs = 'fetchExternalAgentInputs',
  SetAgentSetting = 'setAgentSetting',
  FetchPrompt = 'fetchPrompt',
  CancelDataflow = 'cancelDataflow',
  CancelCanvas = 'cancelCanvas',
  FetchWebhookTrace = 'fetchWebhookTrace',
  FetchSessionsByCanvasId = 'fetchSessionsByCanvasId',
  FetchSessionById = 'fetchSessionById',
  CreateAgentSession = 'createAgentSession',
  DeleteAgentSession = 'deleteAgentSession',
  FetchSessionByIdManually = 'fetchSessionByIdManually',
  FetchAgentLog = 'fetchAgentLog',
  FetchSharedAgent = 'fetchSharedAgent',
  FetchAgentTags = 'fetchAgentTags',
  UpdateAgentTags = 'updateAgentTags',
  FetchPipelineNodes = 'fetchPipelineNodes',
  FetchBuiltinPipelineList = 'fetchBuiltinPipelineList',
  FetchBuiltinPipelineDetail = 'fetchBuiltinPipelineDetail',
}

export const useFetchAgentTemplates = () => {
  const { data } = useQuery<IFlowTemplate[]>({
    queryKey: [AgentApiAction.FetchAgentTemplates],
    initialData: [],
    queryFn: async () => {
      const { data } = await agentService.listAgentTemplate();

      return data.data;
    },
  });

  return data;
};

const buildAgentListParams = ({
  page,
  pageSize,
  keywords,
  canvasCategory,
  ownerIds,
  tags,
}: {
  page: number;
  pageSize: number;
  keywords?: string;
  canvasCategory?: string;
  ownerIds?: string[];
  tags?: string[];
}) => {
  const params: Record<string, unknown> = {
    page,
    page_size: pageSize,
  };

  if (keywords) {
    params.keywords = keywords;
  }
  if (canvasCategory) {
    params.canvas_category = canvasCategory;
  }
  if (Array.isArray(ownerIds) && ownerIds.length > 0) {
    params.owner_ids = ownerIds.join(',');
  }
  if (Array.isArray(tags) && tags.length > 0) {
    params.tags = tags.join(',');
  }

  return params;
};

export const useFetchAgentListByPage = () => {
  const { searchString, handleInputChange } = useHandleSearchChange();
  const { pagination, setPagination } = useGetPaginationWithRouter();
  const debouncedSearchString = useDebounce(searchString, { wait: 500 });
  const { filterValue, handleFilterSubmit } = useHandleFilterSubmit();
  const canvasCategory = Array.isArray(filterValue.canvasCategory)
    ? (filterValue.canvasCategory[0] as string | undefined)
    : undefined;
  const owner = filterValue.owner;
  const tags = Array.isArray(filterValue.tags) ? filterValue.tags : undefined;

  const requestParams = buildAgentListParams({
    page: pagination.current,
    pageSize: pagination.pageSize,
    keywords: debouncedSearchString,
    canvasCategory,
    ownerIds: Array.isArray(owner) ? owner : undefined,
    tags,
  });

  const { data, isFetching: loading } = useQuery<{
    canvas: AgentListItem[];
    total: number;
  }>({
    queryKey: [
      AgentApiAction.FetchAgentListByPage,
      {
        debouncedSearchString,
        ...pagination,
        filterValue,
      },
    ],
    placeholderData: (previousData) => {
      if (previousData === undefined) {
        return { canvas: [], total: 0 };
      }
      return previousData;
    },
    gcTime: 0,
    queryFn: async () => {
      const { data } = await agentService.listAgents(
        {
          params: requestParams,
        },
        true,
      );

      return data?.data;
    },
  });

  const onInputChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(
    (e) => {
      // setPagination({ page: 1 });
      handleInputChange(e);
    },
    [handleInputChange],
  );

  return {
    data: data?.canvas ?? [],
    loading,
    searchString,
    handleInputChange: onInputChange,
    pagination: { ...pagination, total: data?.total ?? 0 },
    setPagination,
    filterValue,
    handleFilterSubmit,
  };
};

export function useFetchAllAgentList() {
  const { data, isFetching: loading } = useQuery<AgentListItem[]>({
    queryKey: [AgentApiAction.FetchAllAgentList],
    queryFn: async () => {
      const { data } = await agentService.listAgents(
        {
          params: buildAgentListParams({
            page: 1,
            pageSize: 100000,
            canvasCategory: AgentCategory.AgentCanvas,
          }),
        },
        true,
      );

      return data?.data?.canvas;
    },
  });

  return { data, loading };
}

export const useUpdateAgentSetting = () => {
  const queryClient = useQueryClient();

  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.UpdateAgentSetting],
    mutationFn: async (params: any) => {
      const ret = await updateAgent(params.id, {
        title: params.title,
        description: params.description,
        permission: params.permission,
        avatar: params.avatar,
      });
      if (ret?.data?.code === 0) {
        message.success('success');
        queryClient.invalidateQueries({
          queryKey: [AgentApiAction.FetchAgentListByPage],
        });
      }
      return ret?.data?.code;
    },
  });

  return { data, loading, updateAgentSetting: mutateAsync };
};

export const useDuplicateAgent = () => {
  const queryClient = useQueryClient();
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.SetAgent, 'duplicate'],
    mutationFn: async (agent: Pick<IFlow, 'id' | 'title'>) => {
      try {
        const { data: detail } = await agentService.getAgent(agent.id);
        const source = detail?.data;
        if (!source) {
          message.error(i18n.t('message.requestError'));
          return null;
        }

        const sourceTitle = agent.title ?? source.title ?? '';
        const { data } = await agentService.createAgent({
          title: i18n.t('flow.copyOfAgentName', {
            name: sourceTitle,
            defaultValue: `${sourceTitle} (Copy)`,
          }),
          dsl: source.dsl,
          avatar: source.avatar,
          description: source.description,
          canvas_category: source.canvas_category,
        });

        if (data?.code === 0) {
          message.success(i18n.t('message.created'));
          queryClient.invalidateQueries({
            queryKey: [AgentApiAction.FetchAgentListByPage],
          });
          return data;
        }

        message.error(data?.message ?? i18n.t('message.requestError'));
        return null;
      } catch (error) {
        console.error('useDuplicateAgent failed:', error);
        message.error(
          (error as { message?: string })?.message ??
            i18n.t('message.requestError'),
        );
        return null;
      }
    },
  });

  return { data, loading, duplicateAgent: mutateAsync };
};

export const useDeleteAgent = () => {
  const queryClient = useQueryClient();
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.DeleteAgent],
    mutationFn: async (agentId: string) => {
      const { data } = await agentService.deleteAgent(agentId);
      if (data.code === 0) {
        queryClient.invalidateQueries({
          queryKey: [AgentApiAction.FetchAgentListByPage],
        });
      }
      return data?.data ?? false;
    },
  });

  return { data, loading, deleteAgent: mutateAsync };
};

export interface IAgentTagCount {
  tag: string;
  count: number;
}

export const useFetchAgentTags = (canvasCategory?: string) => {
  const { data, isFetching: loading } = useQuery<IAgentTagCount[]>({
    queryKey: [AgentApiAction.FetchAgentTags, canvasCategory],
    initialData: [],
    gcTime: 0,
    queryFn: async () => {
      const { data } = await agentService.listAgentTags(
        {
          params: canvasCategory ? { canvas_category: canvasCategory } : {},
        },
        true,
      );
      return data?.data ?? [];
    },
  });
  return { data, loading };
};

export const useUpdateAgentTags = () => {
  const queryClient = useQueryClient();
  const { isPending: loading, mutateAsync } = useMutation({
    mutationKey: [AgentApiAction.UpdateAgentTags],
    mutationFn: async ({
      agentId,
      tags,
    }: {
      agentId: string;
      tags: string[];
    }) => {
      const { data } = await updateAgentTags(agentId, tags);
      if (data?.code === 0) {
        queryClient.invalidateQueries({
          queryKey: [AgentApiAction.FetchAgentListByPage],
        });
        queryClient.invalidateQueries({
          queryKey: [AgentApiAction.FetchAgentTags],
        });
      } else {
        message.error(data?.message || 'Update failed');
      }
      return data?.code === 0;
    },
  });
  return { loading, updateAgentTags: mutateAsync };
};

export const useFetchAgent = (): {
  data: IFlow;
  loading: boolean;
  refetch: () => void;
} => {
  const { id } = useParams();
  const { sharedId } = useGetSharedChatSearchParams();

  const {
    data,
    isFetching: loading,
    refetch,
  } = useQuery({
    queryKey: [AgentApiAction.FetchAgentDetail, sharedId || id],
    initialData: {} as IFlow,
    refetchOnReconnect: false,
    refetchOnMount: false,
    refetchOnWindowFocus: false,
    gcTime: 0,
    queryFn: async () => {
      const { data } = await agentService.getAgent(sharedId || id);

      const messageList = buildMessageListWithUuid(
        get(data, 'data.dsl.messages', []),
      );
      set(data, 'data.dsl.messages', messageList);

      const sysHistoryPath = [
        'data',
        'dsl',
        'globals',
        AgentGlobals.SysHistory,
      ];

      if (isEmpty(get(data, sysHistoryPath))) {
        set(data, sysHistoryPath, []);
      }

      return data?.data ?? {};
    },
  });

  return { data, loading, refetch };
};

export const useResetAgent = () => {
  const { id } = useParams();
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.ResetAgent],
    mutationFn: async () => {
      const { data } = await agentService.resetAgent(id);
      return data;
    },
  });

  return { data, loading, resetAgent: mutateAsync };
};

export const useSetAgent = (
  showMessage: boolean = true,
  skipInvalidation: boolean = false,
) => {
  const { id } = useParams();
  const queryClient = useQueryClient();
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.SetAgent],
    mutationFn: async (params: {
      id?: string;
      title?: string;
      dsl?: Record<string, any>;
      avatar?: string;
      canvas_category?: string;
      release?: string;
      description?: string | null;
      permission?: string;
    }) => {
      const agentId = params.id ?? id;
      const { data = {} } = agentId
        ? await updateAgent(agentId, {
            title: params.title,
            dsl: params.dsl,
            avatar: params.avatar,
            description: params.description,
            permission: params.permission,
            release: params.release,
          })
        : await agentService.createAgent(params);
      if (data.code === 0) {
        if (showMessage) {
          message.success(
            i18n.t(`message.${agentId ? 'modified' : 'created'}`),
          );
        }
        queryClient.invalidateQueries({
          queryKey: [AgentApiAction.FetchAgentListByPage],
        });
        if (agentId && !skipInvalidation) {
          queryClient.invalidateQueries({
            queryKey: [AgentApiAction.FetchAgentDetail, agentId],
          });
        }
      }
      return data;
    },
  });

  return { data, loading, setAgent: mutateAsync };
};

// Only one file can be uploaded at a time
export const useUploadAgentFile = () => {
  const { id } = useParams();
  const [searchParams] = useSearchParams();
  const shared_id = searchParams.get('shared_id');
  const agentId = id || shared_id;
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.UploadAgentFile],
    mutationFn: async (body: any) => {
      let nextBody = body;
      try {
        if (Array.isArray(body)) {
          nextBody = new FormData();
          body.forEach((file: File) => {
            nextBody.append('file', file as any);
          });
        }

        const { data } = await uploadAgentFile(agentId as string, nextBody);
        if (data?.code === 0) {
          message.success(i18n.t('message.uploaded'));
        }
        return data;
      } catch (error) {
        message.error(error as string);
      }
    },
  });

  return { data, loading, uploadAgentFile: mutateAsync };
};

export const useUploadAgentFileWithProgress = (identifier?: string | null) => {
  const { id } = useParams();

  type UploadParameters = Parameters<NonNullable<FileUploadProps['onUpload']>>;

  type X = { files: UploadParameters[0]; options: UploadParameters[1] };

  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.UploadAgentFileWithProgress],
    mutationFn: async ({
      files,
      options: { onError, onSuccess, onProgress },
    }: X) => {
      const formData = new FormData();
      try {
        if (Array.isArray(files)) {
          files.forEach((file: File) => {
            formData.append('file', file);
          });
        }

        const { data } = await agentService.uploadAgentFile(
          {
            agentId: identifier || id,
            data: formData,
            onUploadProgress: ({ progress }) => {
              files.forEach((file) => {
                onProgress(file, (progress || 0) * 100);
              });
            },
          },
          true,
        );
        if (data?.code === 0) {
          files.forEach((file) => {
            onSuccess(file);
          });
          message.success(i18n.t('message.uploaded'));
        }
        return data;
      } catch (error) {
        files.forEach((file) => {
          onError(file, error as Error);
        });
        message.error((error as Error)?.message || 'Upload failed');
      }
    },
  });

  return { data, loading, uploadAgentFile: mutateAsync };
};

export const useFetchMessageTrace = (canvasId?: string, isShare?: boolean) => {
  const { id } = useParams();
  // In shared mode there's no :id route param and `canvasId` actually carries
  // the share (beta) APIToken — route through fetchSharedTrace so the request
  // hits the beta-token-aware endpoint instead of /agents/<id>/logs which
  // requires a session login (fixes #14985).
  const queryId = id || canvasId;
  const [messageId, setMessageId] = useState('');
  const [isStopFetchTrace, setISStopFetchTrace] = useState(false);

  const {
    data,
    isFetching: loading,
    refetch,
  } = useQuery<ITraceData[]>({
    queryKey: [AgentApiAction.Trace, queryId, messageId, !!isShare],
    refetchOnReconnect: false,
    refetchOnMount: false,
    refetchOnWindowFocus: false,
    gcTime: 0,
    enabled: !!queryId && !!messageId,
    refetchInterval: !isStopFetchTrace ? 3000 : false,
    queryFn: async () => {
      const { data } = isShare
        ? await fetchSharedTrace({
            shared_id: queryId as string,
            message_id: messageId,
          })
        : await fetchTrace({
            canvas_id: queryId as string,
            message_id: messageId,
          });

      return Array.isArray(data?.data) ? data?.data : [];
    },
  });

  return {
    data,
    loading,
    refetch,
    setMessageId,
    messageId,
    isStopFetchTrace,
    setISStopFetchTrace,
  };
};

export const useTestDbConnect = () => {
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.TestDbConnect],
    mutationFn: async (params: any) => {
      const ret = await agentService.testDbConnect(params);
      if (ret?.data?.code === 0) {
        message.success(ret?.data?.data);
      } else {
        message.error(ret?.data?.data);
      }
      return ret;
    },
  });

  return { data, loading, testDbConnect: mutateAsync };
};

export const useDebugSingle = () => {
  const { id } = useParams();
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.DebugSingle],
    mutationFn: async (params: IDebugSingleRequestBody) => {
      const ret = await agentService.debugSingle(
        {
          agentId: id as string,
          componentId: params.component_id,
          data: {
            params: params.params,
          },
        },
        true,
      );
      if (ret?.data?.code !== 0) {
        message.error(ret?.data?.message);
      }
      return ret?.data?.data;
    },
  });

  return { data, loading, debugSingle: mutateAsync };
};

export const useFetchInputForm = (componentId?: string) => {
  const { id } = useParams();

  const { data } = useQuery<Record<string, any>>({
    queryKey: [AgentApiAction.FetchInputForm],
    initialData: {},
    enabled: !!id && !!componentId,
    queryFn: async () => {
      const { data } = await agentService.inputForm(
        { agentId: id as string, componentId: componentId as string },
        true,
      );

      return data.data;
    },
  });

  return data;
};

export const useFetchVersionList = () => {
  const { id } = useParams();
  const { data, isFetching: loading } = useQuery<
    Array<{ created_at: string; title: string; id: string; release?: boolean }>
  >({
    queryKey: [AgentApiAction.FetchVersionList],
    initialData: [],
    gcTime: 0,
    queryFn: async () => {
      const { data } = await agentService.fetchVersionList(id);

      return data?.data ?? [];
    },
  });

  return { data, loading };
};

export const useFetchVersion = (
  version_id?: string,
): {
  data?: IFlow;
  loading: boolean;
} => {
  const { id } = useParams();
  const { data, isFetching: loading } = useQuery({
    queryKey: [AgentApiAction.FetchVersion, id, version_id],
    initialData: undefined,
    gcTime: 0,
    enabled: !!id && !!version_id,
    queryFn: async () => {
      if (!id || !version_id) return undefined;

      const { data } = await agentService.fetchVersion({
        agentId: id,
        versionId: version_id,
      });

      return data?.data ?? undefined;
    },
  });

  return { data, loading };
};

export const useFetchAgentLog = (searchParams: IAgentLogsRequest) => {
  const { id } = useParams();
  const {
    data,
    isFetching: loading,
    refetch,
  } = useQuery<IAgentLogsResponse>({
    queryKey: [AgentApiAction.FetchAgentLog, id, searchParams],
    initialData: {} as IAgentLogsResponse,
    gcTime: 0,
    queryFn: async () => {
      const { data } = await fetchAgentLogsByCanvasId(id as string, {
        ...searchParams,
      });

      return { total: data?.total ?? 0, sessions: data?.data ?? [] };
    },
  });

  return { data, loading, refetch };
};

export const useFetchSessionsByCanvasId = () => {
  const { id: canvasId } = useParams();
  const { data: tenantInfo } = useFetchTenantInfo();

  const { data, isFetching: loading } = useQuery<IAgentLogsResponse>({
    queryKey: [AgentApiAction.FetchSessionsByCanvasId, canvasId],
    initialData: { total: 0, sessions: [] } as IAgentLogsResponse,
    gcTime: 0,
    enabled: !!canvasId && !isEmpty(tenantInfo),
    queryFn: async () => {
      if (!canvasId) {
        return { total: 0, sessions: [] };
      }

      const { data } = await fetchAgentLogsByCanvasId(canvasId, {
        page: 1,
        page_size: 100,
        exp_user_id: tenantInfo.tenant_id,
      });

      return { total: data?.total ?? 0, sessions: data?.data ?? [] };
    },
  });

  return {
    data: data?.sessions ?? [],
    loading,
    total: data?.total ?? 0,
  };
};

export const useFetchExternalAgentInputs = () => {
  const { sharedId } = useGetSharedChatSearchParams();

  const {
    data,
    isFetching: loading,
    refetch,
  } = useQuery<IInputs>({
    queryKey: [AgentApiAction.FetchExternalAgentInputs, sharedId],
    initialData: {} as IInputs,
    refetchOnReconnect: false,
    // refetchOnMount: false,
    refetchOnWindowFocus: false,
    gcTime: 0,
    enabled: !!sharedId,
    queryFn: async () => {
      const { data } = await agentService.fetchExternalAgentInputs(sharedId!);

      return data?.data ?? {};
    },
  });

  return { data, loading, refetch };
};

export const useFetchPrompt = () => {
  const {
    data,
    isFetching: loading,
    refetch,
  } = useQuery<Record<string, string>>({
    queryKey: [AgentApiAction.FetchPrompt],
    refetchOnReconnect: false,
    refetchOnMount: false,
    refetchOnWindowFocus: false,
    gcTime: 0,
    queryFn: async () => {
      const { data } = await agentService.fetchPrompt();

      return data?.data ?? {};
    },
  });

  return { data, loading, refetch };
};

export const useFetchAgentList = ({
  canvas_category,
}: IPipeLineListRequest) => {
  const { data, isFetching: loading } = useQuery<{
    canvas: AgentListItem[];
    total: number;
  }>({
    queryKey: [AgentApiAction.FetchAgentList],
    initialData: { canvas: [], total: 0 },
    gcTime: 0,
    queryFn: async () => {
      const { data } = await fetchPipeLineList({
        canvas_category,
      });

      return data?.data ?? [];
    },
  });

  return { data, loading };
};

export const BuiltinPipelineKeys = {
  list: (type: string) =>
    [AgentApiAction.FetchBuiltinPipelineList, type] as const,
  detail: (id: string) =>
    [AgentApiAction.FetchBuiltinPipelineDetail, id] as const,
};

export const useFetchBuiltinPipelines = (type = 'builtin', enabled = true) => {
  const { data, isFetching: loading } = useQuery<IBuiltinPipelineListResponse>({
    queryKey: BuiltinPipelineKeys.list(type),
    initialData: { canvas: [], total: 0 },
    gcTime: 0,
    enabled,
    queryFn: async () => {
      const { data } = await agentService.listBuiltinPipelines(
        { params: { type } },
        true,
      );
      return data?.data ?? { canvas: [], total: 0 };
    },
  });

  const options =
    data?.canvas?.map((item) => ({
      label: item.title,
      value: item.id,
    })) ?? [];

  return { data, loading, options };
};

export const useCancelDataflow = () => {
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.CancelDataflow],
    mutationFn: async (taskId: string) => {
      const ret = await agentService.cancelDataflow(taskId);
      if (ret?.data?.code === 0) {
        message.success('success');
      } else {
        message.error(ret?.data?.data);
      }
      return ret?.data?.code;
    },
  });

  return { data, loading, cancelDataflow: mutateAsync };
};

// export const useFetchKnowledgeList = () => {
//   const { data, isFetching: loading } = useQuery<IFlow[]>({
//     queryKey: [AgentApiAction.FetchAgentList],
//     initialData: [],
//     gcTime: 0, // https://tanstack.com/query/latest/docs/framework/react/guides/caching?from=reactQueryV3
//     queryFn: async () => {
//       const { data } = await agentService.listAgents();

//       return data?.data ?? [];
//     },
//   });

//   return { list: data, loading };
// };

export function useCancelConversation() {
  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.CancelCanvas],
    mutationFn: async (taskId: string) => {
      const ret = await agentService.cancelCanvas(taskId);

      return ret?.data?.code;
    },
  });

  return { data, loading, cancelConversation: mutateAsync };
}

export const useFetchFlowSSE = (): {
  data: IFlow;
  loading: boolean;
  refetch: () => void;
} => {
  const { sharedId } = useGetSharedChatSearchParams();

  const {
    data,
    isFetching: loading,
    refetch,
  } = useQuery({
    queryKey: [AgentApiAction.FetchSharedAgent, sharedId],
    initialData: {} as IFlow,
    enabled: !!sharedId,
    refetchOnReconnect: false,
    refetchOnMount: false,
    refetchOnWindowFocus: false,
    gcTime: 0,
    queryFn: async () => {
      if (!sharedId) return {};
      const { data } = await agentService.getAgent(sharedId);

      const messageList = buildMessageListWithUuid(
        get(data, 'data.dsl.messages', []),
      );
      set(data, 'data.dsl.messages', messageList);

      return data?.data ?? {};
    },
  });

  return { data, loading, refetch };
};

export const useFetchWebhookTrace = (autoStart: boolean = true) => {
  const { id } = useParams();
  const [currentWebhookId, setCurrentWebhookId] = useState<string>('');
  const [currentNextSinceTs, setCurrentNextSinceTs] = useState<number>(0);
  const [shouldPoll, setShouldPoll] = useState(autoStart);

  const {
    data,
    isFetching: loading,
    refetch,
  } = useQuery<IWebhookTrace>({
    queryKey: [AgentApiAction.FetchWebhookTrace, id],
    refetchOnReconnect: false,
    refetchOnMount: false,
    refetchOnWindowFocus: false,
    refetchIntervalInBackground: false,
    gcTime: 0,
    enabled: !!id && shouldPoll,
    queryFn: async () => {
      if (!id) return {};

      const payload: IAgentWebhookTraceRequest =
        {} as IAgentWebhookTraceRequest;

      if (currentNextSinceTs) {
        payload['since_ts'] = currentNextSinceTs;
      }

      if (currentWebhookId) {
        payload['webhook_id'] = currentWebhookId;
      }

      const { data } = await fetchWebhookTrace(id, payload);

      const result = data.data ?? {};

      if (result.webhook_id && result.webhook_id !== currentWebhookId) {
        setCurrentWebhookId(result.webhook_id);
      }

      if (
        currentNextSinceTs === 0 &&
        result.next_since_ts &&
        result.next_since_ts !== currentNextSinceTs
      ) {
        setCurrentNextSinceTs(result.next_since_ts);
      }

      if (result.finished) {
        setShouldPoll(false);
      }

      return result;
    },
    refetchInterval: shouldPoll ? 3000 : false,
  });

  return {
    data,
    loading,
    refetch,
    isPolling: shouldPoll,
    currentWebhookId,
    currentNextSinceTs,
  };
};

export function useCreateAgentSession() {
  const queryClient = useQueryClient();

  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.CreateAgentSession],
    mutationFn: async (payload: { id: string; name: string }) => {
      const { data } = await createAgentSession(payload);

      if (data.code === 0) {
        queryClient.invalidateQueries({
          queryKey: [AgentApiAction.FetchSessionsByCanvasId],
        });
      }

      return data?.data ?? {};
    },
  });

  return { data, loading, createAgentSession: mutateAsync };
}

export function useDeleteAgentSession() {
  const queryClient = useQueryClient();

  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation({
    mutationKey: [AgentApiAction.DeleteAgentSession],
    mutationFn: async ({
      canvasId,
      sessionId,
    }: {
      canvasId: string;
      sessionId: string;
    }) => {
      const { data } = await deleteAgentSession(canvasId, sessionId);

      if (data.code === 0) {
        queryClient.invalidateQueries({
          queryKey: [AgentApiAction.FetchSessionsByCanvasId],
        });
      }

      return data?.code ?? -1;
    },
  });

  return { data, loading, deleteAgentSession: mutateAsync };
}

export function useFetchSessionManually() {
  const { id: canvasId } = useParams();

  const {
    data,
    isPending: loading,
    mutateAsync,
  } = useMutation<IAgentLogResponse, unknown, string>({
    mutationKey: [AgentApiAction.FetchSessionByIdManually, canvasId],
    mutationFn: async (sessionId) => {
      if (!canvasId || !sessionId) {
        return null;
      }

      const { data } = await fetchAgentLogsById(canvasId, sessionId);

      return data?.data;
    },
  });

  return { data, loading, fetchSessionManually: mutateAsync };
}

export const useExportAgentLog = () => {
  const { id } = useParams();
  const { mutateAsync, isPending: loading } = useMutation({
    mutationKey: [AgentApiAction.FetchAgentLog, 'export', id],
    mutationFn: async (searchParams: IAgentLogsRequest) => {
      const { data } = await fetchAgentLogsByCanvasId(id as string, {
        ...searchParams,
      });

      return data?.data ?? [];
    },
  });

  return { exportLogs: mutateAsync, loading };
};

export const useFetchPipelineDslByPipelineId = (
  pipelineId?: string,
  isBuiltin = false,
) => {
  const { data: dsl, isFetching: loading } = useQuery({
    queryKey: isBuiltin
      ? BuiltinPipelineKeys.detail(pipelineId!)
      : [AgentApiAction.FetchPipelineNodes, pipelineId],
    initialData: {},
    gcTime: 0,
    enabled: !!pipelineId,
    queryFn: async () => {
      const { data } = isBuiltin
        ? await agentService.getBuiltinPipeline(pipelineId!)
        : await agentService.getAgent(pipelineId!);
      const flow = data?.data;
      return flow?.dsl ?? {};
    },
  });

  return { dsl, loading };
};
