export type ActionType = 'primary' | 'secondary' | 'tertiary' | 'destructive'

export type Action<T> = {
  name: string
  href?: (row: T) => string
  run?: (row: T) => void
  icon?: string
  type?: ActionType
  disabled?: (row: T) => boolean
  hidden?: (row: T) => boolean
}

export type Column<T, Value = any> = {
  field: string
  name: string
  from: (row: T) => Value
  change?: (row: T, value: Value) => void
  format?: (value: Value) => {
    content: string
    classes?: string[]
    style?: string
  }
  sort: (a: Value, b: Value) => number
  avatar?: (row: T) => string | undefined
  subTitle?: (row: T) => string | undefined
  textAlign: 'left' | 'right'
  order: ('desc' | 'asc')[]
  breakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
  formType?: 'text' | 'number' | 'select' | 'checkbox' | 'date'
}

export type TableDefinition<T> = {
  columns: Column<T>[]
  actions: Action<T>[]
}

function camelCaseToText(str: string) {
  return str.replace(/([A-Z])/g, ' $1').replace(/^./, function (str) {
    return str.toUpperCase()
  })
}

function textToCamelCase(str: string) {
  return str
    .replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) {
      return index === 0 ? word.toLowerCase() : word.toUpperCase()
    })
    .replace(/\s+/g, '')
}

export function tableBuilder<T>() {
  return {
    click(
      name: string,
      run: (row: T) => void,
      options?: Partial<Action<T>>,
    ): Action<T> {
      return { name, run, type: 'primary', ...options }
    },
    link(
      name: string,
      href: (row: T) => string,
      options?: Partial<Action<T>>,
    ): Action<T> {
      return { name, href, type: 'primary', ...options }
    },
    fieldColumn<K extends keyof T>(
      field: K,
      options?: Partial<Column<T, T[K]>>,
    ): Column<T, T[K]> {
      return {
        field: field as string,
        name: camelCaseToText(field as string),
        formType: 'text',
        from: (row: T) => row[field],
        sort: (a: T[K], b: T[K]) => (a > b ? 1 : a < b ? -1 : 0),
        format: (value: T[K]) => ({ content: String(value) }),
        textAlign: 'left',
        order: [],
        ...options,
      }
    },
    displayColumn<V>(
      name: string,
      value: (row: T) => V,
      options?: Partial<Column<T, V>>,
    ): Column<T, V> {
      return {
        field: 'display-' + textToCamelCase(name),
        name,
        formType: 'text',
        from: value,
        sort: (a: V, b: V) => (a > b ? 1 : a < b ? -1 : 0),
        format: (value: V) => ({ content: String(value) }),
        textAlign: 'left',
        order: [],
        ...options,
      }
    },
  }
}

export const css = (strings: TemplateStringsArray, ...values: any[]) =>
  strings.reduce((result, str, i) => result + str + (values[i] || ''), '')
