import type { CSSProperties, ReactNode } from 'react'
import type { ModelAndParameter } from '../configuration/debug/types'
import type { AppPublisherProps } from './index'
import type { PublishWorkflowParams } from '@/types/workflow'
import { Button } from '@langgenius/dify-ui/button'
import { Kbd, KbdGroup } from '@langgenius/dify-ui/kbd'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { formatForDisplay } from '@tanstack/react-hotkeys'
import { useTranslation } from 'react-i18next'
import Divider from '@/app/components/base/divider'
import Loading from '@/app/components/base/loading'
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
import WorkflowToolConfigureButton from '@/app/components/tools/workflow-tool/configure-button'
import { AppModeEnum } from '@/types/app'
import { APP_PUBLISH_HOTKEY } from './hotkeys'
import PublishWithMultipleModel from './publish-with-multiple-model'
import SuggestedAction from './suggested-action'
import { ACCESS_MODE_MAP } from './utils'

type SummarySectionProps = Pick<
  AppPublisherProps,
  | 'debugWithMultipleModel'
  | 'draftUpdatedAt'
  | 'multipleModelConfigs'
  | 'publishDisabled'
  | 'publishedAt'
  | 'startNodeLimitExceeded'
> & {
  formatTimeFromNow: (value: number) => string
  handlePublish: (params?: ModelAndParameter | PublishWorkflowParams) => Promise<void>
  handleRestore: () => Promise<void>
  isChatApp: boolean
  published: boolean
  upgradeHighlightStyle: CSSProperties
}

type AccessSectionProps = {
  enabled: boolean
  isAppAccessSet: boolean
  isLoading: boolean
  accessMode?: keyof typeof ACCESS_MODE_MAP
  onClick: () => void
}

type ActionsSectionProps = Pick<
  AppPublisherProps,
  | 'hasHumanInputNode'
  | 'hasTriggerNode'
  | 'missingStartNode'
  | 'toolPublished'
  | 'publishedAt'
  | 'workflowToolAvailable'
> & {
  appDetail:
    | {
        id?: string
        icon?: string
        icon_type?: string | null
        icon_background?: string | null
        description?: string
        mode?: AppModeEnum
        name?: string
      }
    | null
    | undefined
  appURL: string
  disabledFunctionButton: boolean
  disabledFunctionTooltip?: string
  handleEmbed: () => void
  handleOpenInExplore: () => void
  handleOpenRunConfig?: (url: string) => void
  handlePublish: (params?: ModelAndParameter | PublishWorkflowParams) => Promise<void>
  published: boolean
  showBatchRunConfig?: boolean
  showRunConfig?: boolean
  workflowToolIsLoading: boolean
  workflowToolOutdated: boolean
  workflowToolMessage?: string
  onConfigureWorkflowTool: () => void
}

export const AccessModeDisplay = ({ mode }: { mode?: keyof typeof ACCESS_MODE_MAP }) => {
  const { t } = useTranslation()

  if (!mode || !ACCESS_MODE_MAP[mode]) return null

  const { icon, label } = ACCESS_MODE_MAP[mode]

  return (
    <>
      <span className={`${icon} size-4 shrink-0 text-text-secondary`} />
      <div className="grow truncate">
        <span className="system-sm-medium text-text-secondary">
          {t(($) => $[`accessControlDialog.accessItems.${label}`], { ns: 'app' })}
        </span>
      </div>
    </>
  )
}

export const PublisherSummarySection = ({
  debugWithMultipleModel = false,
  draftUpdatedAt,
  formatTimeFromNow,
  handlePublish,
  handleRestore,
  isChatApp,
  multipleModelConfigs = [],
  publishDisabled = false,
  published,
  publishedAt,
  startNodeLimitExceeded = false,
  upgradeHighlightStyle,
}: SummarySectionProps) => {
  const { t } = useTranslation()

  return (
    <div className="p-4 pt-3">
      <div className="flex h-6 items-center system-xs-medium-uppercase text-text-tertiary">
        {publishedAt
          ? t(($) => $['common.latestPublished'], { ns: 'workflow' })
          : t(($) => $['common.currentDraftUnpublished'], { ns: 'workflow' })}
      </div>
      {publishedAt ? (
        <div className="flex items-center justify-between">
          <div className="flex items-center system-sm-medium text-text-secondary">
            {t(($) => $['common.publishedAt'], { ns: 'workflow' })} {formatTimeFromNow(publishedAt)}
          </div>
          {isChatApp && (
            <Button
              variant="secondary-accent"
              size="small"
              onClick={handleRestore}
              disabled={published}
            >
              {t(($) => $['common.restore'], { ns: 'workflow' })}
            </Button>
          )}
        </div>
      ) : (
        <div className="flex items-center system-sm-medium text-text-secondary">
          {t(($) => $['common.autoSaved'], { ns: 'workflow' })} ·
          {Boolean(draftUpdatedAt) && formatTimeFromNow(draftUpdatedAt!)}
        </div>
      )}
      {debugWithMultipleModel ? (
        <PublishWithMultipleModel
          multipleModelConfigs={multipleModelConfigs}
          onSelect={(item) => handlePublish(item)}
        />
      ) : (
        <>
          <Button
            variant="primary"
            className="mt-3 w-full"
            onClick={() => handlePublish()}
            disabled={publishDisabled || published}
          >
            {published ? (
              t(($) => $['common.published'], { ns: 'workflow' })
            ) : (
              <div className="flex gap-1">
                <span>{t(($) => $['common.publishUpdate'], { ns: 'workflow' })}</span>
                <KbdGroup>
                  {APP_PUBLISH_HOTKEY.split('+').map((key) => (
                    <Kbd key={key} color="white">
                      {formatForDisplay(key)}
                    </Kbd>
                  ))}
                </KbdGroup>
              </div>
            )}
          </Button>
          {startNodeLimitExceeded && (
            <div className="mt-3 flex flex-col items-stretch">
              <p className="text-sm/5 font-semibold text-transparent" style={upgradeHighlightStyle}>
                <span className="block">
                  {t(($) => $['publishLimit.startNodeTitlePrefix'], { ns: 'workflow' })}
                </span>
                <span className="block">
                  {t(($) => $['publishLimit.startNodeTitleSuffix'], { ns: 'workflow' })}
                </span>
              </p>
              <p className="mt-1 text-xs/4 text-text-secondary">
                {t(($) => $['publishLimit.startNodeDesc'], { ns: 'workflow' })}
              </p>
              <UpgradeBtn isShort className="mt-[9px] mb-[12px] h-[32px] w-[93px] self-start" />
            </div>
          )}
        </>
      )}
    </div>
  )
}

export const PublisherAccessSection = ({
  enabled,
  isAppAccessSet,
  isLoading,
  accessMode,
  onClick,
}: AccessSectionProps) => {
  const { t } = useTranslation()

  if (isLoading)
    return (
      <div className="py-2">
        <Loading />
      </div>
    )

  return (
    <>
      <Divider className="my-0" />
      {enabled && (
        <div className="p-4 pt-3">
          <div className="flex h-6 items-center">
            <p className="system-xs-medium text-text-tertiary">
              {t(($) => $['publishApp.title'], { ns: 'app' })}
            </p>
          </div>
          <div
            className="flex h-8 cursor-pointer items-center gap-x-0.5 rounded-lg bg-components-input-bg-normal py-1 pr-2 pl-2.5 hover:bg-primary-50 hover:text-text-accent"
            onClick={onClick}
          >
            <div className="flex grow items-center gap-x-1.5 overflow-hidden pr-1">
              <AccessModeDisplay mode={accessMode} />
            </div>
            {!isAppAccessSet && (
              <p className="shrink-0 system-xs-regular text-text-tertiary">
                {t(($) => $['publishApp.notSet'], { ns: 'app' })}
              </p>
            )}
            <div className="flex size-4 shrink-0 items-center justify-center">
              <span className="i-ri-arrow-right-s-line size-4 text-text-quaternary" />
            </div>
          </div>
          {!isAppAccessSet && (
            <p className="mt-1 system-xs-regular text-text-warning">
              {t(($) => $['publishApp.notSetDesc'], { ns: 'app' })}
            </p>
          )}
        </div>
      )}
    </>
  )
}

const ActionTooltip = ({
  disabled,
  tooltip,
  children,
}: {
  disabled: boolean
  tooltip?: ReactNode
  children: ReactNode
}) => {
  if (!disabled || !tooltip) return <>{children}</>

  return (
    <Tooltip>
      <TooltipTrigger render={<div className="flex">{children}</div>} />
      <TooltipContent>{tooltip}</TooltipContent>
    </Tooltip>
  )
}

export const PublisherActionsSection = ({
  appDetail,
  appURL,
  disabledFunctionButton,
  disabledFunctionTooltip,
  handleEmbed,
  handleOpenInExplore,
  handleOpenRunConfig,
  hasHumanInputNode = false,
  hasTriggerNode = false,
  missingStartNode = false,
  publishedAt,
  showBatchRunConfig = false,
  showRunConfig = false,
  toolPublished,
  workflowToolAvailable = true,
  workflowToolIsLoading,
  workflowToolOutdated,
  workflowToolMessage,
  onConfigureWorkflowTool,
}: ActionsSectionProps) => {
  const { t } = useTranslation()

  if (hasTriggerNode) return null

  const workflowToolDisabled = !publishedAt || !workflowToolAvailable

  return (
    <div className="flex flex-col gap-y-1 border-t-[0.5px] border-t-divider-regular p-4 pt-3">
      <ActionTooltip disabled={disabledFunctionButton} tooltip={disabledFunctionTooltip}>
        <SuggestedAction
          className="flex-1"
          disabled={disabledFunctionButton}
          link={appURL}
          icon={<span className="i-ri-play-circle-line size-4" />}
          actionButton={
            showRunConfig
              ? {
                  ariaLabel: t(($) => $['operation.config'], { ns: 'common' }),
                  icon: <span className="i-ri-settings-2-line size-4" />,
                  onClick: () => handleOpenRunConfig?.(appURL),
                }
              : undefined
          }
        >
          {t(($) => $['common.runApp'], { ns: 'workflow' })}
        </SuggestedAction>
      </ActionTooltip>
      {appDetail?.mode === AppModeEnum.WORKFLOW || appDetail?.mode === AppModeEnum.COMPLETION ? (
        <ActionTooltip disabled={disabledFunctionButton} tooltip={disabledFunctionTooltip}>
          <SuggestedAction
            className="flex-1"
            disabled={disabledFunctionButton}
            link={`${appURL}${appURL.includes('?') ? '&' : '?'}mode=batch`}
            icon={<span className="i-ri-play-list-2-line size-4" />}
            actionButton={
              showBatchRunConfig
                ? {
                    ariaLabel: t(($) => $['operation.config'], { ns: 'common' }),
                    icon: <span className="i-ri-settings-2-line size-4" />,
                    onClick: () =>
                      handleOpenRunConfig?.(
                        `${appURL}${appURL.includes('?') ? '&' : '?'}mode=batch`,
                      ),
                  }
                : undefined
            }
          >
            {t(($) => $['common.batchRunApp'], { ns: 'workflow' })}
          </SuggestedAction>
        </ActionTooltip>
      ) : (
        <SuggestedAction
          onClick={handleEmbed}
          disabled={!publishedAt}
          icon={<span className="i-custom-vender-line-development-code-browser size-4" />}
        >
          {t(($) => $['common.embedIntoSite'], { ns: 'workflow' })}
        </SuggestedAction>
      )}
      <ActionTooltip disabled={disabledFunctionButton} tooltip={disabledFunctionTooltip}>
        <SuggestedAction
          className="flex-1"
          onClick={() => {
            if (publishedAt) handleOpenInExplore()
          }}
          disabled={disabledFunctionButton}
          icon={<span className="i-ri-planet-line size-4" />}
        >
          {t(($) => $['common.openInExplore'], { ns: 'workflow' })}
        </SuggestedAction>
      </ActionTooltip>
      <ActionTooltip
        disabled={!publishedAt || missingStartNode}
        tooltip={
          !publishedAt
            ? t(($) => $.notPublishedYet, { ns: 'app' })
            : t(($) => $.noUserInputNode, { ns: 'app' })
        }
      >
        <SuggestedAction
          className="flex-1"
          disabled={!publishedAt || missingStartNode}
          link="./develop"
          icon={<span className="i-ri-terminal-box-line size-4" />}
        >
          {t(($) => $['common.accessAPIReference'], { ns: 'workflow' })}
        </SuggestedAction>
      </ActionTooltip>
      {appDetail?.mode === AppModeEnum.WORKFLOW && !hasHumanInputNode && (
        <WorkflowToolConfigureButton
          disabled={workflowToolDisabled}
          published={!!toolPublished}
          isLoading={workflowToolIsLoading}
          outdated={workflowToolOutdated}
          onConfigure={onConfigureWorkflowTool}
          disabledReason={workflowToolMessage}
        />
      )}
    </div>
  )
}
