import type { Field, MultiSelect } from "../../../types"
import { Column, ColumnType, MatchColumnsProps, MatchedOptions } from "../types"
import { uniqueEntries } from "./uniqueEntries"

export const setColumn = <T extends string>(
  oldColumn: Column<T>,
  field?: Field<T>,
  data?: MatchColumnsProps<T>["data"],
  autoMapSelectValues?: boolean,
): Column<T> => {
  switch (field?.fieldType.type) {
    case "select":
      const fieldOptions = field.fieldType.options
      const uniqueData = uniqueEntries(data || [], oldColumn.index) as MatchedOptions<T>[]
      const matchedOptions = autoMapSelectValues
        ? uniqueData.map((record) => {
            const value = fieldOptions.find(
              (fieldOption) => fieldOption.value === record.entry || fieldOption.label === record.entry,
            )?.value
            return value ? ({ ...record, value } as MatchedOptions<T>) : (record as MatchedOptions<T>)
          })
        : uniqueData
      const allMatched = matchedOptions.filter((o) => o.value).length == uniqueData?.length

      return {
        ...oldColumn,
        type: allMatched ? ColumnType.matchedSelectOptions : ColumnType.matchedSelect,
        value: field.key,
        matchedOptions,
      }
    case "multi-select":
      const multiSelectFieldType = field.fieldType as MultiSelect
      const multiSelectFieldOptions = multiSelectFieldType.options
      const multiSelectUniqueData = uniqueEntries(data || [], oldColumn.index) as MatchedOptions<T>[]
      const multiSelectMatchedOptions = autoMapSelectValues
        ? multiSelectUniqueData.map((record) => {
            // Split the entry by the separator (default to comma)
            const entries = record.entry.split(multiSelectFieldType.separator || ",").map(e => e.trim())
            // Try to match each entry to an option
            const values = entries.map(entry => {
              const value = multiSelectFieldOptions.find(
                (fieldOption) => fieldOption.value === entry || fieldOption.label === entry,
              )?.value
              return value
            }).filter(Boolean) as T[]
            return { ...record, value: values.length ? values[0] : undefined } as MatchedOptions<T>
          })
        : multiSelectUniqueData

      return {
        ...oldColumn,
        type: ColumnType.matchedMultiSelect,
        value: field.key,
        matchedOptions: multiSelectMatchedOptions,
      }
    case "checkbox":
      return { index: oldColumn.index, type: ColumnType.matchedCheckbox, value: field.key, header: oldColumn.header }
    case "input":
      return { index: oldColumn.index, type: ColumnType.matched, value: field.key, header: oldColumn.header }
    case "multi-input":
      return { index: oldColumn.index, type: ColumnType.matchedMultiInput, value: field.key, header: oldColumn.header }
    default:
      return { index: oldColumn.index, header: oldColumn.header, type: ColumnType.empty }
  }
}
