import type {
  BaseElement,
  EditConfig,
  ElementMetadata,
} from "@/definitions/shared/base"
import type { ValidationConfig } from "@/definitions/shared/validation"

/**
 * Variants of the `input` element type. Each value here maps 1:1 to a
 * Vue file under `src/elements/input/` via the engine's registry.
 */
export type InputStyle =
  | "text"
  | "number"
  | "email"
  | "password"
  | "url"
  | "tel"
  | "search"
  | "textarea"
  | "range-slider"
  | "barcode-scanner"

/**
 * Optional content-type hint used by the `text` style to drive HTML5
 * input mode / pattern. Distinct from `style` because the visual shell
 * is the same — only the keyboard / validation differs.
 */
export type InputContentType = "string" | "number" | "integer" | "decimal"

export interface InputElement extends BaseElement<`input.${InputStyle}`> {
  name: string
  label: string
  placeholder?: string
  defaultValue?: string | number | null
  contentType?: InputContentType
  /** Prepend text/icon inside the input shell. */
  prepend?: string
  /** Append text/icon inside the input shell. */
  append?: string
  maxLength?: number
  minLength?: number
  /** For `number` and `range-slider`. */
  min?: number
  max?: number
  step?: number
  /** For `textarea`. */
  rows?: number
  /** For `range-slider`: number of discrete steps. */
  steps?: number
  /** For `range-slider`: render tick marks. */
  showTicks?: boolean
  /** For `barcode-scanner`: accepted symbologies. */
  scanFormats?: ReadonlyArray<string>
  /** Validation rules (Laravel-style strings). */
  validation?: ValidationConfig
  /** Auto-focus the input on mount. */
  autoFocus?: boolean
  /** Toggle masking on `password`. */
  togglePasswordVisibility?: boolean
}

export const InputElementDefaults = {
  type: "input.text",
  label: "Input Label",
  placeholder: "",
  defaultValue: "",
  columns: 12,
  columnsSm: 12,
  columnsMd: 12,
  columnsLg: 12,
  columnsXl: 12,
} as const satisfies Partial<InputElement>

export const InputElementMetadata = {
  icon: "type",
  displayLabel: "Input Field",
  elementCategory: "input",
  description:
    "A single-line or multi-line text input. Supports text, email, password, URL, number, search, textarea, range slider, and barcode scanner variants.",
} as const satisfies ElementMetadata

/**
 * EditConfig describes how the FormBuilder inspector renders each
 * configurable property. Each key matches a property on `InputElement`;
 * the value is itself a (loosely-typed) element spec.
 *
 * The `section` tag groups properties in the inspector
 * (configuration / layout / advanced / conditions).
 */
export const InputElementEditConfig = {
  label: {
    type: "input.text",
    defaultValue: "",
    label: "Field Label",
    columns: 12,
    section: "configuration",
  },
  name: {
    type: "picker.data-model",
    defaultValue: "",
    label: "Field Name",
    columns: 12,
    section: "advanced",
  },
  style: {
    type: "option-select.select",
    defaultValue: "text",
    label: "Input Style",
    columns: 12,
    selectOptions: [
      { label: "Text", value: "text" },
      { label: "Number", value: "number" },
      { label: "Email", value: "email" },
      { label: "Password", value: "password" },
      { label: "URL", value: "url" },
      { label: "Tel", value: "tel" },
      { label: "Search", value: "search" },
      { label: "Textarea", value: "textarea" },
      { label: "Range Slider", value: "range-slider" },
      { label: "Barcode Scanner", value: "barcode-scanner" },
    ],
    section: "layout",
  },
  placeholder: {
    type: "input.text",
    label: "Placeholder Text",
    columns: 12,
    section: "configuration",
  },
  defaultValue: {
    type: "input.text",
    label: "Default Value",
    columns: 12,
    section: "configuration",
  },
  prepend: {
    type: "input.text",
    label: "Prepend Text",
    columns: 6,
    section: "layout",
  },
  append: {
    type: "input.text",
    label: "Append Text",
    columns: 6,
    section: "layout",
  },
  required: {
    type: "boolean.switch",
    label: "Required",
    columns: 6,
    section: "configuration",
  },
  readonly: {
    type: "boolean.switch",
    label: "Read-only",
    columns: 6,
    section: "configuration",
  },
  maxLength: {
    type: "input.text",
    contentType: "integer",
    label: "Max Length",
    columns: 6,
    section: "configuration",
  },
  minLength: {
    type: "input.text",
    contentType: "integer",
    label: "Min Length",
    columns: 6,
    section: "configuration",
  },
  min: {
    type: "input.text",
    contentType: "number",
    label: "Min Value",
    columns: 6,
    section: "configuration",
    conditionParams: [
      { name: "style", logic: "in-array", value: ["number", "range-slider"] },
    ],
  },
  max: {
    type: "input.text",
    contentType: "number",
    label: "Max Value",
    columns: 6,
    section: "configuration",
    conditionParams: [
      { name: "style", logic: "in-array", value: ["number", "range-slider"] },
    ],
  },
  step: {
    type: "input.text",
    contentType: "number",
    label: "Step",
    columns: 6,
    section: "configuration",
    conditionParams: [
      { name: "style", logic: "in-array", value: ["number", "range-slider"] },
    ],
  },
  rows: {
    type: "input.text",
    contentType: "integer",
    label: "Rows",
    columns: 6,
    section: "layout",
    conditionParams: [{ name: "style", logic: "==", value: "textarea" }],
  },
} as const satisfies EditConfig

export const InputStyleMetadataMap: Partial<Record<InputStyle, { displayLabel: string; description: string }>> = {
  text: { displayLabel: "Text", description: "A single-line text input field." },
  number: { displayLabel: "Number", description: "A numeric input with optional min, max, and step." },
  email: { displayLabel: "Email", description: "An email address input with format validation." },
  password: { displayLabel: "Password", description: "A masked password input with optional visibility toggle." },
  url: { displayLabel: "URL", description: "A URL input with format validation." },
  tel: { displayLabel: "Phone", description: "A telephone number input." },
  search: { displayLabel: "Search", description: "A search input with a clear button." },
  textarea: { displayLabel: "Textarea", description: "A multi-line text input with configurable row height." },
  "range-slider": { displayLabel: "Range Slider", description: "A slider for selecting a value within a numeric range." },
  "barcode-scanner": { displayLabel: "Barcode Scanner", description: "A camera-powered barcode/QR code scanner input." },
}
