import type { IComponentModelConfig } from '@/lvgl-widgets/type'
import type { BaseWidget } from '@/types/baseWidget'
import type { Page } from '@/types/page'

import componentMap from '@/lvgl-widgets'
import { customAlphabet } from 'nanoid'
import { bfsWalk } from 'simple-mind-map/src/utils'

type WidgetNameSource =
  | Pick<BaseWidget, 'type' | 'name'>
  | Pick<IComponentModelConfig, 'key' | 'defaultSchema'>

const createNameSuffix = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 5)
const widgetNameSuffixPattern = /_\d+(?:_[0-9A-Za-z]+)?$/

const getWidgetType = (source: WidgetNameSource) => {
  return 'key' in source ? source.key : source.type
}

const getRawWidgetName = (source: WidgetNameSource) => {
  return 'defaultSchema' in source ? source.defaultSchema?.name : source.name
}

export const getWidgetNameBase = (source: WidgetNameSource) => {
  const widgetType = getWidgetType(source)
  const defaultName = widgetType ? componentMap[widgetType]?.defaultSchema?.name : ''
  const rawName = String(defaultName || getRawWidgetName(source) || '')
  const normalizedBaseName = rawName.replace(widgetNameSuffixPattern, '')

  return normalizedBaseName || 'widget'
}

export const createWidgetName = (source: WidgetNameSource, index: number) => {
  return `${getWidgetNameBase(source)}_${index}_${createNameSuffix()}`
}

const collectWidgetTypeCounts = (page?: Page) => {
  const counts: Record<string, number> = {}
  if (!page) return counts

  bfsWalk(page, (widget) => {
    if (!widget?.type) return
    counts[widget.type] = (counts[widget.type] || 0) + 1
  })

  return counts
}

export const createWidgetNameGenerator = (page?: Page) => {
  const widgetTypeCounts = collectWidgetTypeCounts(page)

  return (source: WidgetNameSource) => {
    const widgetType = getWidgetType(source) || 'widget'
    const nextIndex = (widgetTypeCounts[widgetType] || 0) + 1
    widgetTypeCounts[widgetType] = nextIndex

    return createWidgetName(source, nextIndex)
  }
}

export const isDuplicateWidgetName = (
  widgets: Array<{ id: string; name: string }>,
  name: string,
  currentId?: string
) => {
  const normalizedName = name.trim()
  if (!normalizedName) return false

  return widgets.some((widget) => widget.id !== currentId && widget.name === normalizedName)
}
