import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
import { memo } from 'react'
import AppIcon from '@/app/components/base/app-icon'
import {
  Agent,
  Answer,
  Assigner,
  Code,
  Datasource,
  DocsExtractor,
  End,
  Home,
  Http,
  HumanInLoop,
  IfElse,
  Iteration,
  KnowledgeBase,
  KnowledgeRetrieval,
  ListFilter,
  Llm,
  Loop,
  LoopEnd,
  ParameterExtractor,
  QuestionClassifier,
  Schedule,
  TemplatingTransform,
  VariableX,
  WebhookLine,
} from '@/app/components/base/icons/src/vender/workflow'
import { API_PREFIX } from '@/config'
import { BlockEnum } from './types'

type BlockIconProps = {
  type: BlockEnum
  size?: string
  className?: string
  toolIcon?: string | { content: string; background: string }
}
const ICON_CONTAINER_CLASSNAME_SIZE_MAP: Record<string, string> = {
  xs: 'w-4 h-4 rounded-[5px] shadow-xs',
  sm: 'w-5 h-5 rounded-md shadow-xs',
  md: 'w-6 h-6 rounded-lg shadow-md',
}

const DEFAULT_ICON_MAP: Record<BlockEnum, React.ComponentType<{ className: string }>> = {
  [BlockEnum.Start]: Home,
  [BlockEnum.StartPlaceholder]: Home,
  [BlockEnum.LLM]: Llm,
  [BlockEnum.Code]: Code,
  [BlockEnum.End]: End,
  [BlockEnum.IfElse]: IfElse,
  [BlockEnum.HttpRequest]: Http,
  [BlockEnum.Answer]: Answer,
  [BlockEnum.KnowledgeRetrieval]: KnowledgeRetrieval,
  [BlockEnum.QuestionClassifier]: QuestionClassifier,
  [BlockEnum.TemplateTransform]: TemplatingTransform,
  [BlockEnum.VariableAssigner]: VariableX,
  [BlockEnum.VariableAggregator]: VariableX,
  [BlockEnum.Assigner]: Assigner,
  [BlockEnum.Tool]: VariableX,
  [BlockEnum.IterationStart]: VariableX,
  [BlockEnum.Iteration]: Iteration,
  [BlockEnum.LoopStart]: VariableX,
  [BlockEnum.Loop]: Loop,
  [BlockEnum.LoopEnd]: LoopEnd,
  [BlockEnum.ParameterExtractor]: ParameterExtractor,
  [BlockEnum.DocExtractor]: DocsExtractor,
  [BlockEnum.ListFilter]: ListFilter,
  [BlockEnum.Agent]: Agent,
  [BlockEnum.AgentV2]: Agent,
  [BlockEnum.KnowledgeBase]: KnowledgeBase,
  [BlockEnum.DataSource]: Datasource,
  [BlockEnum.DataSourceEmpty]: () => null,
  [BlockEnum.TriggerSchedule]: Schedule,
  [BlockEnum.TriggerWebhook]: WebhookLine,
  [BlockEnum.TriggerPlugin]: VariableX,
  [BlockEnum.HumanInput]: HumanInLoop,
}

const getIcon = (type: BlockEnum, className: string) => {
  const DefaultIcon = DEFAULT_ICON_MAP[type]
  if (!DefaultIcon) return null

  return <DefaultIcon className={className} />
}

const normalizeToolIconUrl = (toolIcon: string) => {
  const protectedPluginIconPath = '/workspaces/current/plugin/icon'
  const pathIndex = toolIcon.indexOf(protectedPluginIconPath)

  if (pathIndex < 0) return toolIcon

  return `${API_PREFIX}${toolIcon.slice(pathIndex)}`
}

const ICON_CONTAINER_BG_COLOR_MAP: Record<string, string> = {
  [BlockEnum.Start]: 'bg-util-colors-blue-brand-blue-brand-500',
  [BlockEnum.StartPlaceholder]: 'bg-util-colors-blue-brand-blue-brand-500',
  [BlockEnum.LLM]: 'bg-util-colors-indigo-indigo-500',
  [BlockEnum.Code]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.End]: 'bg-util-colors-warning-warning-500',
  [BlockEnum.IfElse]: 'bg-util-colors-cyan-cyan-500',
  [BlockEnum.Iteration]: 'bg-util-colors-cyan-cyan-500',
  [BlockEnum.Loop]: 'bg-util-colors-cyan-cyan-500',
  [BlockEnum.LoopEnd]: 'bg-util-colors-warning-warning-500',
  [BlockEnum.HttpRequest]: 'bg-util-colors-violet-violet-500',
  [BlockEnum.Answer]: 'bg-util-colors-warning-warning-500',
  [BlockEnum.KnowledgeRetrieval]: 'bg-util-colors-green-green-500',
  [BlockEnum.QuestionClassifier]: 'bg-util-colors-green-green-500',
  [BlockEnum.TemplateTransform]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.VariableAssigner]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.VariableAggregator]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.Tool]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.Assigner]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.ParameterExtractor]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.DocExtractor]: 'bg-util-colors-green-green-500',
  [BlockEnum.ListFilter]: 'bg-util-colors-cyan-cyan-500',
  [BlockEnum.Agent]: 'bg-util-colors-indigo-indigo-500',
  [BlockEnum.AgentV2]: 'bg-util-colors-indigo-indigo-500',
  [BlockEnum.HumanInput]: 'bg-util-colors-cyan-cyan-500',
  [BlockEnum.KnowledgeBase]: 'bg-util-colors-warning-warning-500',
  [BlockEnum.DataSource]: 'bg-components-icon-bg-midnight-solid',
  [BlockEnum.TriggerSchedule]: 'bg-util-colors-violet-violet-500',
  [BlockEnum.TriggerWebhook]: 'bg-util-colors-blue-blue-500',
  [BlockEnum.TriggerPlugin]: 'bg-util-colors-blue-blue-500',
}
const BlockIcon: FC<BlockIconProps> = ({ type, size = 'sm', className, toolIcon }) => {
  const isStart = type === BlockEnum.Start
  const isStartPlaceholder = type === BlockEnum.StartPlaceholder
  const isToolOrDataSourceOrTriggerPlugin =
    type === BlockEnum.Tool || type === BlockEnum.DataSource || type === BlockEnum.TriggerPlugin
  const showDefaultIcon = !isToolOrDataSourceOrTriggerPlugin || !toolIcon
  const resolvedToolIcon = typeof toolIcon === 'string' ? normalizeToolIconUrl(toolIcon) : toolIcon

  if (isStart) {
    return (
      <div
        className={cn(
          'flex items-center justify-center border-[0.5px] border-white/2 bg-util-colors-blue-brand-blue-brand-500 text-white',
          ICON_CONTAINER_CLASSNAME_SIZE_MAP[size],
          className,
        )}
      >
        <span
          aria-hidden
          className={cn('i-custom-vender-workflow-user-input', size === 'xs' ? 'size-4' : 'size-4')}
        />
      </div>
    )
  }

  if (isStartPlaceholder) {
    return (
      <div
        className={cn(
          'flex items-center justify-center border border-dashed border-components-panel-border bg-state-base-hover text-text-tertiary shadow-none',
          ICON_CONTAINER_CLASSNAME_SIZE_MAP[size],
          className,
        )}
      >
        <span
          aria-hidden
          className={cn(
            'i-custom-vender-workflow-start-placeholder text-text-primary opacity-30',
            size === 'xs' ? 'size-3' : 'size-3.5',
          )}
        />
      </div>
    )
  }

  return (
    <div
      className={cn(
        'flex items-center justify-center border-[0.5px] border-white/2 text-white',
        ICON_CONTAINER_CLASSNAME_SIZE_MAP[size],
        showDefaultIcon && ICON_CONTAINER_BG_COLOR_MAP[type],
        toolIcon && 'shadow-none!',
        className,
      )}
    >
      {showDefaultIcon &&
        getIcon(
          type,
          type === BlockEnum.TriggerSchedule || type === BlockEnum.TriggerWebhook
            ? size === 'xs'
              ? 'w-4 h-4'
              : 'w-4.5 h-4.5'
            : size === 'xs'
              ? 'w-3 h-3'
              : 'w-3.5 h-3.5',
        )}
      {!showDefaultIcon && (
        <>
          {typeof resolvedToolIcon === 'string' ? (
            <div
              className="size-full shrink-0 rounded-md bg-cover bg-center"
              style={{
                backgroundImage: `url(${resolvedToolIcon})`,
              }}
            ></div>
          ) : (
            <AppIcon
              className="size-full! shrink-0"
              size="tiny"
              icon={resolvedToolIcon?.content}
              background={resolvedToolIcon?.background}
            />
          )}
        </>
      )}
    </div>
  )
}

export const VarBlockIcon: FC<BlockIconProps> = ({ type, className }) => {
  return <>{getIcon(type, `w-3 h-3 ${className}`)}</>
}

export default memo(BlockIcon)
