export const INTEGRATION_SECTION_VALUES = [
  'provider',
  'builtin',
  'mcp',
  'custom-tool',
  'workflow-tool',
  'data-source',
  'custom-endpoint',
  'trigger',
  'agent-strategy',
  'extension',
] as const

export type IntegrationSection = (typeof INTEGRATION_SECTION_VALUES)[number]

export const TOOL_CATEGORY_VALUES = ['builtin', 'api', 'workflow', 'mcp'] as const
export type ToolCategory = (typeof TOOL_CATEGORY_VALUES)[number]

export type LegacyToolsSearchParams = Record<string, string | string[] | undefined>
export type IntegrationRouteSearchParams = Record<string, string | string[] | undefined>

const integrationSectionSet = new Set<string>(INTEGRATION_SECTION_VALUES)
const toolCategorySet = new Set<string>(TOOL_CATEGORY_VALUES)

const isIntegrationSection = (value: string): value is IntegrationSection => {
  return integrationSectionSet.has(value)
}

const isToolCategory = (value: string): value is ToolCategory => {
  return toolCategorySet.has(value)
}

const getFirstSearchParamValue = (value: string | string[] | undefined) => {
  if (Array.isArray(value)) return value[0]

  return value
}

const appendSearchParams = (path: string, searchParams: IntegrationRouteSearchParams = {}) => {
  const params = new URLSearchParams()

  Object.entries(searchParams).forEach(([key, value]) => {
    if (value === undefined) return

    if (Array.isArray(value)) {
      value.forEach((item) => params.append(key, item))
      return
    }

    params.set(key, value)
  })

  const query = params.toString()
  return query ? `${path}?${query}` : path
}

export const toolCategoryBySection: Partial<Record<IntegrationSection, ToolCategory>> = {
  builtin: 'builtin',
  mcp: 'mcp',
  'custom-tool': 'api',
  'workflow-tool': 'workflow',
}

export const sectionByToolCategory: Record<ToolCategory, IntegrationSection> = {
  builtin: 'builtin',
  api: 'custom-tool',
  workflow: 'workflow-tool',
  mcp: 'mcp',
}

export const marketplaceUrlPathByIntegrationSection: Partial<Record<IntegrationSection, string>> = {
  provider: '/plugins/model',
  builtin: '/plugins/tool',
  mcp: '/plugins/tool',
  'custom-tool': '/plugins/tool',
  'workflow-tool': '/plugins/tool',
  'data-source': '/plugins/datasource',
  'custom-endpoint': '/plugins/extension',
  trigger: '/plugins/trigger',
  'agent-strategy': '/plugins/agent-strategy',
  extension: '/plugins/extension',
}

export const integrationPathBySection: Record<IntegrationSection, string> = {
  provider: '/integrations/model-provider',
  builtin: '/integrations/tools/built-in',
  'custom-tool': '/integrations/tools/api',
  'workflow-tool': '/integrations/tools/workflow',
  mcp: '/integrations/tools/mcp',
  'data-source': '/integrations/data-source',
  'custom-endpoint': '/integrations/custom-endpoint',
  trigger: '/integrations/trigger',
  'agent-strategy': '/integrations/agent-strategy',
  extension: '/integrations/extension',
}

export const buildIntegrationPath = (section: IntegrationSection) => {
  return integrationPathBySection[section]
}
export const buildMarketplaceUrlPathByIntegrationSection = (section: IntegrationSection) => {
  return marketplaceUrlPathByIntegrationSection[section] ?? '/plugins'
}

export const getIntegrationRedirectPathByLegacyToolsSearchParams = (
  searchParams: LegacyToolsSearchParams = {},
) => {
  const sectionParam = getFirstSearchParamValue(searchParams.section)
  const categoryParam = getFirstSearchParamValue(searchParams.category)
  const section =
    sectionParam && isIntegrationSection(sectionParam)
      ? sectionParam
      : categoryParam && isToolCategory(categoryParam)
        ? sectionByToolCategory[categoryParam]
        : 'builtin'

  const preservedSearchParams = new URLSearchParams()
  Object.entries(searchParams).forEach(([key, value]) => {
    if (key === 'section' || key === 'category' || value === undefined) return

    if (Array.isArray(value)) {
      value.forEach((item) => preservedSearchParams.append(key, item))
      return
    }

    preservedSearchParams.set(key, value)
  })

  const query = preservedSearchParams.toString()
  return query ? `${buildIntegrationPath(section)}?${query}` : buildIntegrationPath(section)
}

type IntegrationRouteTarget =
  | { type: 'redirect'; destination: string }
  | { type: 'section'; section: IntegrationSection }
  | { type: 'not-found' }

const getSectionByCanonicalPath = (path: string) => {
  const entry = Object.entries(integrationPathBySection).find(([, sectionPath]) => {
    return sectionPath.replace('/integrations/', '') === path
  })

  return entry?.[0] as IntegrationSection | undefined
}

export const getIntegrationRouteTargetBySlug = (
  slug?: string[],
  searchParams?: IntegrationRouteSearchParams,
): IntegrationRouteTarget => {
  const path = slug?.join('/') ?? ''
  const nestedMarketplaceCallbackPath = path.endsWith('/plugins')
    ? path.slice(0, -'/plugins'.length)
    : undefined
  const nestedMarketplaceCallbackSection = nestedMarketplaceCallbackPath
    ? getSectionByCanonicalPath(nestedMarketplaceCallbackPath)
    : undefined

  if (nestedMarketplaceCallbackSection) {
    return {
      type: 'redirect',
      destination: appendSearchParams(
        buildIntegrationPath(nestedMarketplaceCallbackSection),
        searchParams,
      ),
    }
  }

  switch (path) {
    case '':
      return { type: 'redirect', destination: buildIntegrationPath('provider') }
    case 'model-provider':
      return { type: 'section', section: 'provider' }
    case 'tools':
      return { type: 'redirect', destination: buildIntegrationPath('builtin') }
    case 'tools/built-in':
      return { type: 'section', section: 'builtin' }
    case 'tool/api':
      return {
        type: 'redirect',
        destination: appendSearchParams(buildIntegrationPath('custom-tool'), searchParams),
      }
    case 'tools/api':
      return { type: 'section', section: 'custom-tool' }
    case 'tools/workflow':
      return { type: 'section', section: 'workflow-tool' }
    case 'tools/mcp':
      return { type: 'section', section: 'mcp' }
    case 'data-source':
      return { type: 'section', section: 'data-source' }
    case 'custom-endpoint':
      return { type: 'section', section: 'custom-endpoint' }
    case 'trigger':
      return { type: 'section', section: 'trigger' }
    case 'agent-strategy':
      return { type: 'section', section: 'agent-strategy' }
    case 'extension':
      return { type: 'section', section: 'extension' }
    default:
      return { type: 'not-found' }
  }
}
