import EmbedDialog, {
  defaultWidgetSettings,
  type WidgetSettings,
} from '@/components/embed-dialog';
import { useShowEmbedModal } from '@/components/embed-dialog/use-show-embed-dialog';
import { PageHeader } from '@/components/page-header';
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from '@/components/ui/breadcrumb';
import { Button, ButtonLoading } from '@/components/ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import message from '@/components/ui/message';
import { SharedFrom } from '@/constants/chat';
import { useSetModalState } from '@/hooks/common-hooks';
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { useSetAgent } from '@/hooks/use-agent-request';
import { ReactFlowProvider } from '@xyflow/react';
import {
  ChevronDown,
  CirclePlay,
  Compass,
  History,
  LaptopMinimalCheck,
  Logs,
  MessageSquareCode,
  ScreenShare,
  Settings,
  Upload,
} from 'lucide-react';
import { ComponentPropsWithoutRef, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router';
import AgentCanvas from './canvas';
import { DropdownProvider } from './canvas/context';
import { PublishConfirmDialog } from './components/publish-confirm-dialog';
import { Operator } from './constant';
import { OwnerTenantIdContext } from './context';
import { GlobalParamSheet } from './gobal-variable-sheet';
import { useBuildDslData } from './hooks/use-build-dsl';
import { useCancelCurrentDataflow } from './hooks/use-cancel-dataflow';
import { useHandleExportJsonFile } from './hooks/use-export-json';
import { useFetchDataOnMount } from './hooks/use-fetch-data';
import { useFetchPipelineLog } from './hooks/use-fetch-pipeline-log';
import { useGetBeginNodeDataInputs } from './hooks/use-get-begin-query';
import { useIsPipeline } from './hooks/use-is-pipeline';
import {
  useIsConversationMode,
  useIsWebhookMode,
} from './hooks/use-is-webhook';
import { useRunDataflow } from './hooks/use-run-dataflow';
import {
  useSaveGraph,
  useSaveGraphBeforeOpeningDebugDrawer,
  useWatchAgentChange,
} from './hooks/use-save-graph';
import { PipelineLogSheet } from './pipeline-log-sheet';
import PipelineRunSheet from './pipeline-run-sheet';
import { SettingDialog } from './setting-dialog';
import useGraphStore from './store';
import { useAgentHistoryManager } from './use-agent-history-manager';
import { VersionDialog } from './version-dialog';
import WebhookSheet from './webhook-sheet';

/**
 * Standardizes dropdown menu item styling for agent management actions.
 */
function AgentDropdownMenuItem({
  children,
  ...props
}: ComponentPropsWithoutRef<typeof DropdownMenuItem>) {
  return (
    <DropdownMenuItem className="justify-start" {...props}>
      {children}
    </DropdownMenuItem>
  );
}

const AgentWidgetSettingsGlobalKey = 'sys.widget_settings';

/**
 * Displays the agent editor and persists agent-scoped widget defaults in DSL globals.
 */
export default function Agent() {
  const { id } = useParams();
  const isPipeline = useIsPipeline();
  const { navigateToAgents } = useNavigatePage();
  const {
    visible: chatDrawerVisible,
    hideModal: hideChatDrawer,
    showModal: showChatDrawer,
  } = useSetModalState();
  const { t } = useTranslation();
  useAgentHistoryManager();

  const { handleExportJson } = useHandleExportJsonFile();
  const { saveGraph, loading } = useSaveGraph();
  const { flowDetail: agentDetail } = useFetchDataOnMount();
  const { buildDslData } = useBuildDslData();
  const { setAgent, loading: savingWidgetSettings } = useSetAgent(false);
  const inputs = useGetBeginNodeDataInputs();
  const { handleRun } = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer);
  const handleRunAgent = useCallback(() => {
    if (inputs.length > 0) {
      showChatDrawer();
    } else {
      handleRun();
    }
  }, [handleRun, inputs, showChatDrawer]);
  const {
    visible: versionDialogVisible,
    hideModal: hideVersionDialog,
    showModal: showVersionDialog,
  } = useSetModalState();

  const {
    visible: settingDialogVisible,
    hideModal: hideSettingDialog,
    showModal: showSettingDialog,
  } = useSetModalState();

  const { showEmbedModal, hideEmbedModal, embedVisible, beta } =
    useShowEmbedModal();
  const { navigateToAgentLogs, navigateToAgentExplore } = useNavigatePage();
  const time = useWatchAgentChange(chatDrawerVisible);
  const isWebhookMode = useIsWebhookMode();

  const isConversationMode = useIsConversationMode();

  // pipeline

  const {
    visible: pipelineRunSheetVisible,
    hideModal: hidePipelineRunSheet,
    showModal: showPipelineRunSheet,
  } = useSetModalState();

  const {
    visible: webhookTestSheetVisible,
    hideModal: hideWebhookTestSheet,
    showModal: showWebhookTestSheet,
  } = useSetModalState();

  const {
    visible: pipelineLogSheetVisible,
    showModal: showPipelineLogSheet,
    hideModal: hidePipelineLogSheet,
  } = useSetModalState();

  const {
    visible: globalParamSheetVisible,
    showModal: showGlobalParamSheet,
    hideModal: hideGlobalParamSheet,
  } = useSetModalState();

  const {
    isParsing,
    logs,
    messageId,
    setMessageId,
    isCompleted,
    stopFetchTrace,
    isLogEmpty,
  } = useFetchPipelineLog(pipelineLogSheetVisible);

  const findNodeByName = useGraphStore((state) => state.findNodeByName);

  const handleRunPipeline = useCallback(() => {
    if (!findNodeByName(Operator.Tokenizer)) {
      message.warning(t('flow.tokenizerRequired'));
      return;
    }

    if (isParsing) {
      // show log sheet
      showPipelineLogSheet();
    } else {
      hidePipelineLogSheet();
      // handleRun();
      showPipelineRunSheet();
    }
  }, [
    findNodeByName,
    hidePipelineLogSheet,
    isParsing,
    showPipelineLogSheet,
    showPipelineRunSheet,
    t,
  ]);

  const { handleCancel } = useCancelCurrentDataflow({
    messageId,
    stopFetchTrace,
  });

  const handleButtonRunClick = useCallback(() => {
    if (isWebhookMode) {
      saveGraph();
      showWebhookTestSheet();
    } else if (isPipeline) {
      handleRunPipeline();
    } else {
      handleRunAgent();
    }
  }, [
    handleRunAgent,
    handleRunPipeline,
    isPipeline,
    isWebhookMode,
    saveGraph,
    showWebhookTestSheet,
  ]);

  const {
    run: runPipeline,
    loading: pipelineRunning,
    uploadedFileData,
  } = useRunDataflow({ showLogSheet: showPipelineLogSheet, setMessageId });

  const initialWidgetSettings = useMemo<WidgetSettings>(() => {
    const widgetSettings =
      agentDetail?.dsl?.globals?.[AgentWidgetSettingsGlobalKey];

    return {
      ...defaultWidgetSettings,
      ...(widgetSettings && typeof widgetSettings === 'object'
        ? widgetSettings
        : {}),
    };
  }, [agentDetail]);

  const handleSaveWidgetSettings = useCallback(
    async (widgetSettings: WidgetSettings) => {
      const dsl = buildDslData();

      return setAgent({
        id: id!,
        title: agentDetail.title,
        dsl: {
          ...dsl,
          globals: {
            ...dsl.globals,
            [AgentWidgetSettingsGlobalKey]: widgetSettings,
          },
        },
      });
    },
    [agentDetail.title, buildDslData, id, setAgent],
  );

  return (
    <section className="h-full" data-testid="agent-detail">
      <PageHeader>
        <section>
          <Breadcrumb>
            <BreadcrumbList>
              <BreadcrumbItem>
                <BreadcrumbLink onClick={navigateToAgents}>
                  {t('header.flow')}
                </BreadcrumbLink>
              </BreadcrumbItem>
              <BreadcrumbSeparator />
              <BreadcrumbItem>
                <BreadcrumbPage>{agentDetail.title}</BreadcrumbPage>
              </BreadcrumbItem>
            </BreadcrumbList>
          </Breadcrumb>
          <div className="text-xs text-text-secondary translate-y-3">
            {t('flow.autosaved')} {time}
          </div>
        </section>
        <div className="flex items-center gap-5">
          <ButtonLoading
            variant={'secondary'}
            onClick={() => saveGraph()}
            loading={loading}
          >
            <LaptopMinimalCheck /> {t('flow.save')}
          </ButtonLoading>
          <Button
            data-testid="agent-run"
            variant={'secondary'}
            onClick={handleButtonRunClick}
          >
            <CirclePlay />
            {t('flow.run')}
          </Button>
          {isConversationMode && (
            <Button
              variant={'secondary'}
              onClick={navigateToAgentExplore(id as string)}
            >
              <Compass />
              {t('explore.title')}
            </Button>
          )}
          <PublishConfirmDialog
            agentDetail={agentDetail}
            loading={loading}
            onPublish={() => saveGraph(undefined, undefined, true)}
          />
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant={'secondary'}>
                <ChevronDown /> {t('flow.management')}
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent>
              <AgentDropdownMenuItem onClick={() => showGlobalParamSheet()}>
                <MessageSquareCode />
                {t('flow.conversationVariable')}
              </AgentDropdownMenuItem>
              <DropdownMenuSeparator />
              <AgentDropdownMenuItem onClick={showVersionDialog}>
                <History />
                {t('flow.historyVersion')}
              </AgentDropdownMenuItem>
              <DropdownMenuSeparator />
              {isPipeline || (
                <AgentDropdownMenuItem
                  onClick={() => navigateToAgentLogs(id as string)()}
                >
                  <Logs />
                  {t('flow.log')}
                </AgentDropdownMenuItem>
              )}
              <DropdownMenuSeparator />
              <AgentDropdownMenuItem onClick={handleExportJson}>
                <Upload />
                {t('flow.export')}
              </AgentDropdownMenuItem>
              <DropdownMenuSeparator />
              <AgentDropdownMenuItem onClick={showSettingDialog}>
                <Settings />
                {t('flow.setting')}
              </AgentDropdownMenuItem>
              {isPipeline ||
                (location.hostname !== 'cloud.ragflow.io' && (
                  <>
                    <DropdownMenuSeparator />
                    <AgentDropdownMenuItem onClick={showEmbedModal}>
                      <ScreenShare />
                      {t('common.embedIntoSite')}
                    </AgentDropdownMenuItem>
                  </>
                ))}
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </PageHeader>
      <OwnerTenantIdContext.Provider value={agentDetail?.user_id}>
        <ReactFlowProvider>
          <DropdownProvider>
            <AgentCanvas
              drawerVisible={chatDrawerVisible}
              hideDrawer={hideChatDrawer}
            ></AgentCanvas>
          </DropdownProvider>
        </ReactFlowProvider>
      </OwnerTenantIdContext.Provider>
      {embedVisible && (
        <EmbedDialog
          visible={embedVisible}
          hideModal={hideEmbedModal}
          token={id!}
          from={SharedFrom.Agent}
          beta={beta}
          isAgent
          initialWidgetSettings={initialWidgetSettings}
          onSaveWidgetSettings={handleSaveWidgetSettings}
          savingWidgetSettings={savingWidgetSettings}
        ></EmbedDialog>
      )}
      {versionDialogVisible && (
        <DropdownProvider>
          <VersionDialog hideModal={hideVersionDialog}></VersionDialog>
        </DropdownProvider>
      )}
      {settingDialogVisible && (
        <SettingDialog hideModal={hideSettingDialog}></SettingDialog>
      )}

      {pipelineLogSheetVisible && (
        <PipelineLogSheet
          hideModal={hidePipelineLogSheet}
          isParsing={isParsing}
          isCompleted={isCompleted}
          isLogEmpty={isLogEmpty}
          logs={logs}
          handleCancel={handleCancel}
          messageId={messageId}
          uploadedFileData={uploadedFileData}
        ></PipelineLogSheet>
      )}
      {pipelineRunSheetVisible && (
        <PipelineRunSheet
          hideModal={hidePipelineRunSheet}
          run={runPipeline}
          loading={pipelineRunning}
        ></PipelineRunSheet>
      )}
      {globalParamSheetVisible && (
        <GlobalParamSheet
          data={{}}
          hideModal={hideGlobalParamSheet}
        ></GlobalParamSheet>
      )}
      {webhookTestSheetVisible && (
        <WebhookSheet hideModal={hideWebhookTestSheet}></WebhookSheet>
      )}
    </section>
  );
}
