import { useCallback, useMemo } from 'react'

import { FileItem, TFileAttributes, TFileId, TFileItemList, TQueueOperationContext } from '../types'

/**
 * Build accessors that let queue-item operations read and write per-file
 * attributes without ever mutating the current `value` list. All changes are
 * propagated via `onFileUpdated`, so controlled parents stay authoritative.
 */
export const useFileAttributes = (
  value: TFileItemList,
  onFileUpdated: (fileId: TFileId, updates: Partial<FileItem>) => void,
) => {
  const getAttributeForFile = useCallback(
    <T>(fileId: TFileId, attributeName: string): T | undefined => {
      const fileItem = value.find((file) => file.fileId === fileId)
      return fileItem?.attributes?.[attributeName] as T | undefined
    },
    [value],
  )

  const setAttributeForFile = useCallback(
    (fileId: TFileId, attributeName: string, attributeValue: unknown) => {
      const fileItem = value.find((file) => file.fileId === fileId)
      if (!fileItem) return
      const nextAttributes = { ...fileItem.attributes, [attributeName]: attributeValue }
      if (attributeValue === undefined) {
        delete nextAttributes[attributeName]
      }
      onFileUpdated(fileId, { attributes: nextAttributes as FileItem['attributes'] })
    },
    [onFileUpdated, value],
  )

  const fileAttributes: TFileAttributes = useMemo(
    () =>
      <T>(attributeName: string) => ({
        get: (fileId: TFileId) => getAttributeForFile<T>(fileId, attributeName),
        set: (fileId: TFileId, attributeValue: T | undefined) =>
          setAttributeForFile(fileId, attributeName, attributeValue),
      }),
    [getAttributeForFile, setAttributeForFile],
  )

  const buildAttributeAccessors = useCallback(
    (fileId: TFileId): Pick<TQueueOperationContext, 'getAttribute' | 'setAttribute'> => ({
      getAttribute: <T>(name: string) => getAttributeForFile<T>(fileId, name),
      setAttribute: (name, attributeValue) => setAttributeForFile(fileId, name, attributeValue),
    }),
    [getAttributeForFile, setAttributeForFile],
  )

  return { fileAttributes, buildAttributeAccessors } as const
}
