import { DSLImportStatus } from '@/models/app'
import { AppModeEnum } from '@/types/app'
import { BlockEnum } from '../types'
import {
  getImportNotificationPayload,
  getInvalidNodeTypes,
  isImportCompleted,
  normalizeWorkflowFeatures,
  validateDSLContent,
} from '../update-dsl-modal.helpers'

describe('update-dsl-modal helpers', () => {
  describe('dsl validation', () => {
    it('should reject advanced chat dsl content with disallowed trigger nodes', () => {
      const content = `
workflow:
  graph:
    nodes:
      - data:
          type: trigger-webhook
`

      expect(validateDSLContent(content, AppModeEnum.ADVANCED_CHAT)).toBe(false)
    })

    it('should reject disallowed node types inherited through YAML merge keys', () => {
      const content = `
trigger: &trigger
  type: trigger-webhook
workflow:
  graph:
    nodes:
      - data:
          <<: *trigger
`

      expect(validateDSLContent(content, AppModeEnum.ADVANCED_CHAT)).toBe(false)
    })

    it('should reject malformed yaml and answer nodes in non-advanced mode', () => {
      expect(validateDSLContent('[', AppModeEnum.CHAT)).toBe(false)
      expect(
        validateDSLContent(
          `
workflow:
  graph:
    nodes:
      - data:
          type: answer
`,
          AppModeEnum.CHAT,
        ),
      ).toBe(false)
    })

    it('should accept valid node types for advanced chat mode', () => {
      expect(
        validateDSLContent(
          `
workflow:
  graph:
    nodes:
      - data:
          type: tool
`,
          AppModeEnum.ADVANCED_CHAT,
        ),
      ).toBe(true)
    })

    it('should accept empty yaml content', () => {
      expect(validateDSLContent('', AppModeEnum.CHAT)).toBe(true)
    })

    it('should accept comment-only yaml content', () => {
      expect(validateDSLContent('# No document', AppModeEnum.CHAT)).toBe(true)
    })

    it('should reject yaml streams with multiple documents', () => {
      expect(validateDSLContent('---\n{}\n---\n{}', AppModeEnum.CHAT)).toBe(false)
    })

    it('should expose the invalid node sets per mode', () => {
      expect(getInvalidNodeTypes(AppModeEnum.ADVANCED_CHAT)).toEqual(
        expect.arrayContaining([BlockEnum.End, BlockEnum.TriggerWebhook]),
      )
      expect(getInvalidNodeTypes(AppModeEnum.CHAT)).toEqual([BlockEnum.Answer])
    })
  })

  describe('status and feature normalization', () => {
    it('should treat completed statuses as successful imports', () => {
      expect(isImportCompleted(DSLImportStatus.COMPLETED)).toBe(true)
      expect(isImportCompleted(DSLImportStatus.COMPLETED_WITH_WARNINGS)).toBe(true)
      expect(isImportCompleted(DSLImportStatus.PENDING)).toBe(false)
    })

    it('should use distinct Agent warning messages in the import notification', () => {
      const t = ((key: (selector: Record<string, string>) => string) =>
        key({
          'common.importSuccess': 'Import succeeded',
          'common.importWarning': 'Caution',
          'common.importWarningDetails': 'Some configuration may need attention',
        })) as never

      const payload = getImportNotificationPayload(DSLImportStatus.COMPLETED_WITH_WARNINGS, t, [
        {
          code: 'agent_file_omitted',
          path: 'agent_packages.agent_1.omitted_assets',
          message: "Agent file 'brief.pdf' was not included.",
          details: {},
        },
        {
          code: 'agent_file_omitted',
          path: 'agent_packages.agent_1.omitted_assets',
          message: "Agent file 'brief.pdf' was not included.",
          details: {},
        },
        {
          code: 'agent_tool_authorization_required',
          path: 'agent_packages.agent_1.soul.tools.dify_tools.0',
          message: "Agent tool 'web_search' requires authorization.",
          details: {},
        },
      ])

      expect(payload).toEqual({
        type: 'warning',
        message: 'Caution',
        children:
          "Agent file 'brief.pdf' was not included. · Agent tool 'web_search' requires authorization.",
      })
    })

    it('should normalize workflow features with defaults', () => {
      const features = normalizeWorkflowFeatures({
        file_upload: {
          image: {
            enabled: true,
          },
        },
        opening_statement: 'hello',
        suggested_questions: ['what can you do?'],
      })

      expect(features.file.enabled).toBe(true)
      expect(features.file.number_limits).toBe(3)
      expect(features.opening.enabled).toBe(true)
      expect(features.suggested).toEqual({ enabled: false })
      expect(features.text2speech).toEqual({ enabled: false })
    })
  })
})
