import { z } from 'zod'

export type NumberFilter = {
  values?: (number | string)[]
  min?: number | null
  max?: number | null
}
export type DateFilter = {
  values?: string[]
  start?: string | null
  end?: string | null
}

export const zNumberFilter = z.object({
  values: z.array(z.union([z.number(), z.string()])).optional(),
  min: z.number().nullable().optional(),
  max: z.number().nullable().optional(),
})

export const zDateFilter = z.object({
  values: z.array(z.string()).optional(),
  start: z.string().nullable().optional(),
  end: z.string().nullable().optional(),
})

export type FilterFieldType = 'string' | 'number' | 'date' | 'boolean'

export type FilterValue = string[] | boolean[] | NumberFilter | DateFilter | undefined

export type FilterFieldName = string & { __brand?: 'FilterFieldName' }

export type FilterState = Record<FilterFieldName, FilterValue>

type BaseFilterConfig<TFilters extends FilterState> = {
  filterKey: keyof TFilters
  valueType: FilterFieldType
}

export type RelationFilterConfig<TFilters extends FilterState> = BaseFilterConfig<TFilters> & {
  kind: 'relation'
  referencedModelViewServiceVariableName: string
  referencedModelLabelField: string
  referencedModelIdField: string
}

type EnumFilterConfig<TFilters extends FilterState> = BaseFilterConfig<TFilters> & {
  kind: 'enum'
  enumName: string
  enumValues: string[]
}

type DiscriminatedUnionFilterConfig<TFilters extends FilterState> = BaseFilterConfig<TFilters> & {
  kind: 'discriminatedUnion'
  duMemberTypes: { type: string; label: string }[]
}

type ScalarFilterConfig<TFilters extends FilterState> = BaseFilterConfig<TFilters> & {
  kind: 'scalar' | 'id'
}

export type FilterConfigItem<TFilters extends FilterState> =
  | RelationFilterConfig<TFilters>
  | EnumFilterConfig<TFilters>
  | DiscriminatedUnionFilterConfig<TFilters>
  | ScalarFilterConfig<TFilters>

export type FilterConfig<TField extends FilterFieldName, TFilters extends FilterState> = Record<
  TField,
  FilterConfigItem<TFilters>
>
