export type EntityType = string
export type EntityId = string
export interface EntityRef { entityType: EntityType; entityId: EntityId }

export interface LocationRule { entityType: EntityType; subType?: string }

export const FIELD_TYPES = [
  'text', 'textarea', 'number', 'boolean', 'select',
  'date', 'color', 'url', 'email', 'media', 'relationship',
] as const
export type FieldType = (typeof FIELD_TYPES)[number]

/** stable machine key + storage/read key */
export const FIELD_KEY_RE = /^[a-z][a-z0-9_]*$/

const MULTIPLE_CAPABLE: ReadonlySet<FieldType> = new Set(['select', 'media', 'relationship'])
export function isMultipleCapable(t: FieldType): boolean { return MULTIPLE_CAPABLE.has(t) }

export type MediaRef = { key: string; url?: string; mime?: string; meta?: Record<string, unknown> }
export type RelRef = EntityRef

export type ScalarValue = string | number | boolean | Date | MediaRef | RelRef
export type FieldValue = ScalarValue | ScalarValue[]
export type FieldValueMap = Record<string, FieldValue | undefined>

export interface BaseField {
  key: string
  label: string
  required?: boolean
  help?: string
  defaultValue?: FieldValue
}
export interface TextField extends BaseField { type: 'text'; maxLength?: number; pattern?: string }
export interface TextAreaField extends BaseField { type: 'textarea'; maxLength?: number }
export interface NumberField extends BaseField { type: 'number'; min?: number; max?: number; integer?: boolean }
export interface BooleanField extends BaseField { type: 'boolean' }
export interface SelectField extends BaseField { type: 'select'; options: { value: string; label: string }[]; multiple?: boolean }
export interface DateField extends BaseField { type: 'date' }
export interface ColorField extends BaseField { type: 'color' }
export interface UrlField extends BaseField { type: 'url' }
export interface EmailField extends BaseField { type: 'email' }
export interface MediaField extends BaseField { type: 'media'; accept?: string[]; multiple?: boolean }
export interface RelationshipField extends BaseField { type: 'relationship'; targetEntityType: EntityType; multiple?: boolean }

export type FieldDefinition =
  | TextField | TextAreaField | NumberField | BooleanField | SelectField
  | DateField | ColorField | UrlField | EmailField | MediaField | RelationshipField

export interface FieldGroup {
  key: string
  label: string
  location: LocationRule
  fields: FieldDefinition[]
  position?: number
}
export type FieldOrigin = 'code' | 'db'
export interface ResolvedFieldGroup extends FieldGroup { origin: FieldOrigin; id?: string }

export interface Actor { id: string; canEditFields?: boolean; canManageGroups?: boolean }

export type Facet =
  | { field: string; op: 'eq' | 'in'; value: string | string[] }
  | { field: string; op: 'eq' | 'lt' | 'lte' | 'gt' | 'gte'; value: number }
  | { field: string; op: 'between'; min: number; max: number }
  | { field: string; op: 'has-ref'; refType: EntityType; refId: EntityId }

export type RelRefResolver = (ref: EntityRef) => Promise<boolean>
