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

/**
 * Variants of the `picker` element type. Each value here maps 1:1 to a
 * Vue file under `src/elements/picker/` via the engine's registry.
 *
 * Note: the v2 schema uses both `icon` and `icon-picker` for icon
 * selection at different points; we accept both so JSON authored against
 * the platform deserialises without translation.
 */
export type PickerStyle =
  | "date-picker"
  | "datetime-picker"
  | "time-picker"
  | "timezone-picker"
  | "color-picker"
  | "icon-picker"
  | "icon-picker-inline"
  | "icon"
  | "map-picker"
  | "async-select"
  | "data-model"
  | "integration-connector"

/**
 * Format string for `color-picker` output.
 */
export type ColorPickerFormat = "hex" | "hexa" | "rgb" | "rgba" | "hsl" | "hsla"

export interface PickerElement extends BaseElement<`picker.${PickerStyle}`> {
  name: string
  label?: string
  defaultValue?: string | number | null
  required?: boolean
  readonly?: boolean

  /** For `date-picker` / `datetime-picker` / `time-picker`: display/storage format. */
  format?: string
  /** For `date-picker` / `datetime-picker`: earliest selectable value (ISO string). */
  minDate?: string
  /** For `date-picker` / `datetime-picker`: latest selectable value (ISO string). */
  maxDate?: string
  /** For `time-picker`: minute step. */
  minuteStep?: number

  /** For `color-picker`: output format. */
  colorFormat?: ColorPickerFormat
  /** For `color-picker`: show alpha channel. */
  showAlpha?: boolean
  /** For `color-picker`: preset swatches. */
  swatches?: ReadonlyArray<string>

  /** For `map-picker`: starting latitude. */
  defaultLat?: number
  /** For `map-picker`: starting longitude. */
  defaultLng?: number
  /** For `map-picker`: starting zoom level. */
  defaultZoom?: number

  /** For `async-select` / `data-model`: remote search endpoint. */
  searchRoute?: RouteRef
  /** For `async-select`: minimum chars before searching. */
  minSearchLength?: number
  /** For `async-select` / `data-model`: option label field. */
  labelField?: string
  /** For `async-select` / `data-model`: option value field. */
  valueField?: string

  /** For `data-model`: the data-model key path being picked. */
  modelKey?: string

  /** For `integration-connector`: connector identifier. */
  connectorKey?: string
  /** For `integration-connector`: free-form config payload passed to the connector. */
  connectorConfig?: Record<string, unknown>

  /** Validation rules (Laravel-style strings). */
  validation?: ValidationConfig
}

export const PickerElementDefaults = {
  type: "picker.color-picker",
  label: "Picker Label",
  defaultValue: null,
  columns: 12,
  columnsSm: 12,
  columnsMd: 12,
  columnsLg: 12,
  columnsXl: 12,
} as const satisfies Partial<PickerElement>

export const PickerElementMetadata = {
  icon: "crosshairs",
  displayLabel: "Custom Pickers",
  elementCategory: "picker",
  description:
    "Create a picker field to allow users to select a color, date, time, icon, map location, timezone, or remote/async selection and more.",
} as const satisfies ElementMetadata

/**
 * EditConfig describes how the FormBuilder inspector renders each
 * configurable property. Each key matches a property on `PickerElement`;
 * the value is a (loosely-typed) element spec.
 */
export const PickerElementEditConfig = {
  label: {
    type: "input.text",
    defaultValue: "",
    label: "Label",
    columns: 12,
    columnsMd: 6,
    section: "configuration",
  },
  name: {
    type: "picker.data-model",
    defaultValue: "",
    label: "Name",
    columns: 12,
    section: "configuration",
  },
  style: {
    type: "option-select.select",
    defaultValue: "color-picker",
    label: "Picker Style",
    columns: 6,
    selectOptions: [
      { label: "Date Picker", value: "date-picker" },
      { label: "Datetime Picker", value: "datetime-picker" },
      { label: "Time Picker", value: "time-picker" },
      { label: "Timezone Picker", value: "timezone-picker" },
      { label: "Color Picker", value: "color-picker" },
      { label: "Icon Picker", value: "icon-picker" },
      { label: "Map Picker", value: "map-picker" },
      { label: "Async Select", value: "async-select" },
      { label: "Data Model Picker", value: "data-model" },
      { label: "Integration Connector", value: "integration-connector" },
    ],
    section: "layout",
  },
  defaultValue: {
    type: "input.text",
    label: "Default Value",
    columns: 12,
    columnsMd: 6,
    section: "configuration",
  },
  format: {
    type: "input.text",
    label: "Format",
    columns: 6,
    section: "configuration",
    conditionParams: [
      {
        name: "style",
        logic: "in-array",
        value: ["date-picker", "datetime-picker", "time-picker"],
      },
    ],
  },
  minDate: {
    type: "input.text",
    label: "Min Date (ISO)",
    columns: 6,
    section: "configuration",
    conditionParams: [
      {
        name: "style",
        logic: "in-array",
        value: ["date-picker", "datetime-picker"],
      },
    ],
  },
  maxDate: {
    type: "input.text",
    label: "Max Date (ISO)",
    columns: 6,
    section: "configuration",
    conditionParams: [
      {
        name: "style",
        logic: "in-array",
        value: ["date-picker", "datetime-picker"],
      },
    ],
  },
  minuteStep: {
    type: "input.text",
    contentType: "integer",
    defaultValue: 1,
    label: "Minute Step",
    columns: 6,
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "time-picker" }],
  },
  colorFormat: {
    type: "option-select.select",
    defaultValue: "hex",
    label: "Color Format",
    columns: 6,
    selectOptions: [
      { label: "Hex", value: "hex" },
      { label: "Hex (with alpha)", value: "hexa" },
      { label: "RGB", value: "rgb" },
      { label: "RGBA", value: "rgba" },
      { label: "HSL", value: "hsl" },
      { label: "HSLA", value: "hsla" },
    ],
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "color-picker" }],
  },
  showAlpha: {
    type: "boolean.switch",
    label: "Show Alpha Channel",
    columns: 6,
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "color-picker" }],
  },
  defaultLat: {
    type: "input.text",
    contentType: "number",
    label: "Default Latitude",
    columns: 4,
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "map-picker" }],
  },
  defaultLng: {
    type: "input.text",
    contentType: "number",
    label: "Default Longitude",
    columns: 4,
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "map-picker" }],
  },
  defaultZoom: {
    type: "input.text",
    contentType: "integer",
    label: "Default Zoom",
    columns: 4,
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "map-picker" }],
  },
  searchRoute: {
    type: "input.text",
    label: "Search Route",
    columns: 12,
    section: "configuration",
    conditionParams: [
      {
        name: "style",
        logic: "in-array",
        value: ["async-select", "data-model"],
      },
    ],
  },
  minSearchLength: {
    type: "input.text",
    contentType: "integer",
    defaultValue: 1,
    label: "Min Search Length",
    columns: 6,
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "async-select" }],
  },
  labelField: {
    type: "input.text",
    label: "Label Field",
    columns: 6,
    section: "configuration",
    conditionParams: [
      {
        name: "style",
        logic: "in-array",
        value: ["async-select", "data-model"],
      },
    ],
  },
  valueField: {
    type: "input.text",
    label: "Value Field",
    columns: 6,
    section: "configuration",
    conditionParams: [
      {
        name: "style",
        logic: "in-array",
        value: ["async-select", "data-model"],
      },
    ],
  },
  modelKey: {
    type: "input.text",
    label: "Model Key",
    columns: 12,
    section: "configuration",
    conditionParams: [{ name: "style", logic: "==", value: "data-model" }],
  },
  connectorKey: {
    type: "input.text",
    label: "Connector Key",
    columns: 12,
    section: "configuration",
    conditionParams: [
      { name: "style", logic: "==", value: "integration-connector" },
    ],
  },
  required: {
    type: "boolean.switch",
    label: "Make item required",
    columns: 6,
    section: "configuration",
  },
  readonly: {
    type: "boolean.switch",
    label: "Make item read-only",
    columns: 6,
    section: "configuration",
  },
} as const satisfies EditConfig

export const PickerStyleMetadataMap: Partial<Record<PickerStyle, { displayLabel: string; description: string }>> = {
  "date-picker": { displayLabel: "Date", description: "A calendar date picker." },
  "datetime-picker": { displayLabel: "Date & Time", description: "A combined date and time picker." },
  "time-picker": { displayLabel: "Time", description: "A time-of-day picker." },
  "timezone-picker": { displayLabel: "Timezone", description: "A searchable timezone selector." },
  "color-picker": { displayLabel: "Color", description: "A colour wheel and swatch picker." },
  "icon-picker": { displayLabel: "Icon", description: "A searchable icon selector." },
  "icon-picker-inline": { displayLabel: "Icon Picker Inline", description: "A searchable picker that returns a chosen icon identifier." },
  "map-picker": { displayLabel: "Map", description: "An interactive map for picking a geographic location." },
  "async-select": { displayLabel: "Async Select", description: "A remote-search selection picker." },
  "data-model": { displayLabel: "Data Model", description: "A picker that navigates and selects from a data model path." },
  "integration-connector": { displayLabel: "Integration Connector", description: "A picker backed by a third-party integration connector." },
}
