import { FolderOpen, List, Lock, Globe, Phone, Calendar, AlignLeft, ToggleLeft, Circle, ChevronDown, CheckSquare, Hash, Type, Mail } from 'lucide-react';
import { z } from 'zod';
import { defineComponent } from '../types.mjs';
import { baseMetaSchema, objectValidationSchema, arrayValidationSchema, baseMetaSchemaWithPlaceholder, DEFAULT_VALUE_SCHEMAS, stringValidationSchema, dateValidationSchema, booleanValidationSchema, enumOptionsSchema, numberValidationSchema } from '../validation-schemas.mjs';

function toNumber(value) {
  if (value == null || value === "") return void 0;
  const num = Number(value);
  return isNaN(num) ? void 0 : num;
}
function buildInputProps(placeholder, inputType) {
  const props = {};
  if (placeholder) props.placeholder = placeholder;
  if (inputType) props.type = inputType;
  return Object.keys(props).length > 0 ? props : void 0;
}
function getPlaceholder(prop) {
  return prop.inputProps?.placeholder || prop.placeholder;
}
function getLabel(prop, key) {
  return prop.label || prop.title || key;
}
const textFieldDefinition = defineComponent({
  type: "text",
  backingType: "string",
  label: "Text Input",
  icon: Type,
  defaultProps: {
    label: "Text Field",
    placeholder: "",
    required: false
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(stringValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    inputProps: buildInputProps(props.placeholder),
    default: props.defaultValue,
    minLength: toNumber(props.minLength),
    maxLength: toNumber(props.maxLength)
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || prop.enum || prop.fieldType || prop.inputType || prop.format || prop.inputProps?.type) {
      return null;
    }
    return {
      id: key,
      type: "text",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default,
        minLength: prop.minLength,
        maxLength: prop.maxLength
      }
    };
  }
});
const emailFieldDefinition = defineComponent({
  type: "email",
  backingType: "string",
  label: "Email",
  icon: Mail,
  defaultProps: {
    label: "Email",
    placeholder: "email@example.com",
    required: false
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    inputProps: buildInputProps(props.placeholder, "email"),
    default: props.defaultValue,
    format: "email"
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || prop.format !== "email" && prop.inputType !== "email" && prop.inputProps?.type !== "email") {
      return null;
    }
    return {
      id: key,
      type: "email",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default
      }
    };
  }
});
const numberFieldDefinition = defineComponent({
  type: "number",
  backingType: "number",
  label: "Number",
  icon: Hash,
  defaultProps: {
    label: "Number",
    required: false
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(numberValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.number })),
  toJSONSchema: (props) => ({
    type: "number",
    label: props.label,
    description: props.description,
    inputProps: buildInputProps(props.placeholder),
    default: props.defaultValue,
    // toNumber handles form input which may come as strings
    minimum: toNumber(props.min),
    maximum: toNumber(props.max)
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "number" && prop.type !== "integer") {
      return null;
    }
    return {
      id: key,
      type: "number",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default,
        min: prop.minimum,
        max: prop.maximum
      }
    };
  }
});
const textareaFieldDefinition = defineComponent({
  type: "textarea",
  backingType: "string",
  label: "Text Area",
  icon: AlignLeft,
  defaultProps: {
    label: "Text Area",
    placeholder: "",
    required: false
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(stringValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    fieldType: "textarea",
    inputProps: buildInputProps(props.placeholder),
    default: props.defaultValue,
    minLength: toNumber(props.minLength),
    maxLength: toNumber(props.maxLength)
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || prop.fieldType !== "textarea") {
      return null;
    }
    return {
      id: key,
      type: "textarea",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default,
        minLength: prop.minLength,
        maxLength: prop.maxLength
      }
    };
  }
});
const checkboxFieldDefinition = defineComponent({
  type: "checkbox",
  backingType: "boolean",
  label: "Checkbox",
  icon: CheckSquare,
  defaultProps: {
    label: "Checkbox",
    required: false
  },
  propertiesSchema: baseMetaSchema.merge(booleanValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.boolean })),
  toJSONSchema: (props) => ({
    type: "boolean",
    label: props.label,
    description: props.description,
    default: props.defaultValue
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "boolean" || prop.fieldType === "switch") {
      return null;
    }
    return {
      id: key,
      type: "checkbox",
      props: {
        label: getLabel(prop, key),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default
      }
    };
  }
});
const switchFieldDefinition = defineComponent({
  type: "switch",
  backingType: "boolean",
  label: "Switch",
  icon: ToggleLeft,
  defaultProps: {
    label: "Switch",
    required: false
  },
  propertiesSchema: baseMetaSchema.merge(booleanValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.boolean })),
  toJSONSchema: (props) => ({
    type: "boolean",
    label: props.label,
    description: props.description,
    fieldType: "switch",
    default: props.defaultValue
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "boolean" || prop.fieldType !== "switch") {
      return null;
    }
    return {
      id: key,
      type: "switch",
      props: {
        label: getLabel(prop, key),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default
      }
    };
  }
});
const selectFieldDefinition = defineComponent({
  type: "select",
  backingType: "enum",
  label: "Select",
  icon: ChevronDown,
  defaultProps: {
    label: "Select Field",
    required: false,
    options: ["Option 1", "Option 2", "Option 3"]
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(enumOptionsSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.enum })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    inputProps: buildInputProps(props.placeholder),
    default: props.defaultValue,
    enum: props.options
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || !prop.enum || prop.fieldType === "radio") {
      return null;
    }
    return {
      id: key,
      type: "select",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default,
        options: prop.enum
      }
    };
  }
});
const radioFieldDefinition = defineComponent({
  type: "radio",
  backingType: "enum",
  label: "Radio Group",
  icon: Circle,
  defaultProps: {
    label: "Radio Group",
    required: false,
    options: ["Option 1", "Option 2", "Option 3"]
  },
  propertiesSchema: baseMetaSchema.merge(enumOptionsSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.enum })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    fieldType: "radio",
    default: props.defaultValue,
    enum: props.options
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || !prop.enum || prop.fieldType !== "radio") {
      return null;
    }
    return {
      id: key,
      type: "radio",
      props: {
        label: getLabel(prop, key),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default,
        options: prop.enum
      }
    };
  }
});
const passwordFieldDefinition = defineComponent({
  type: "password",
  backingType: "string",
  label: "Password",
  icon: Lock,
  defaultProps: {
    label: "Password",
    placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
    required: false
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(stringValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    inputProps: buildInputProps(props.placeholder, "password"),
    default: props.defaultValue,
    minLength: toNumber(props.minLength),
    maxLength: toNumber(props.maxLength)
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || prop.inputType !== "password" && prop.inputProps?.type !== "password") {
      return null;
    }
    return {
      id: key,
      type: "password",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default,
        minLength: prop.minLength,
        maxLength: prop.maxLength
      }
    };
  }
});
const urlFieldDefinition = defineComponent({
  type: "url",
  backingType: "string",
  label: "Website URL",
  icon: Globe,
  defaultProps: {
    label: "Website",
    placeholder: "https://example.com",
    required: false
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    inputProps: buildInputProps(props.placeholder),
    default: props.defaultValue,
    format: "uri"
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || prop.format !== "uri") {
      return null;
    }
    return {
      id: key,
      type: "url",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default
      }
    };
  }
});
const phoneFieldDefinition = defineComponent({
  type: "phone",
  backingType: "string",
  label: "Phone Number",
  icon: Phone,
  defaultProps: {
    label: "Phone Number",
    placeholder: "+1 (555) 123-4567",
    required: false
  },
  propertiesSchema: baseMetaSchemaWithPlaceholder.merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
  toJSONSchema: (props) => ({
    type: "string",
    label: props.label,
    description: props.description,
    inputProps: buildInputProps(props.placeholder, "tel"),
    default: props.defaultValue
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || prop.inputType !== "tel" && prop.inputProps?.type !== "tel") {
      return null;
    }
    return {
      id: key,
      type: "phone",
      props: {
        label: getLabel(prop, key),
        placeholder: getPlaceholder(prop),
        description: prop.description,
        required: isRequired,
        defaultValue: prop.default
      }
    };
  }
});
const dateFieldDefinition = defineComponent({
  type: "date",
  backingType: "date",
  label: "Date Picker",
  icon: Calendar,
  defaultProps: {
    label: "Date",
    required: false
  },
  propertiesSchema: baseMetaSchema.merge(dateValidationSchema),
  toJSONSchema: (props) => ({
    type: "string",
    format: "date-time",
    fieldType: "date",
    label: props.label,
    description: props.description
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "string" || prop.format !== "date-time" && prop.fieldType !== "date") {
      return null;
    }
    return {
      id: key,
      type: "date",
      props: {
        label: getLabel(prop, key),
        description: prop.description,
        required: isRequired
      }
    };
  }
});
const objectFieldDefinition = {
  type: "object",
  label: "Field Group",
  icon: FolderOpen,
  defaultProps: {
    label: "Field Group",
    required: false
  },
  propertiesSchema: baseMetaSchema.extend(objectValidationSchema.shape),
  toJSONSchema: (props) => ({
    type: "object",
    label: props.label,
    description: props.description,
    // properties will be filled in by schema-utils from field.children
    properties: {}
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "object" || !prop.properties) {
      return null;
    }
    return {
      id: key,
      type: "object",
      props: {
        label: getLabel(prop, key),
        description: prop.description,
        required: isRequired
      },
      // children will be filled in by schema-utils
      children: []
    };
  }
};
const arrayFieldDefinition = {
  type: "array",
  label: "Repeating Group",
  icon: List,
  defaultProps: {
    label: "Items",
    required: false
  },
  propertiesSchema: baseMetaSchema.extend(arrayValidationSchema.shape),
  toJSONSchema: (props) => ({
    type: "array",
    label: props.label,
    description: props.description,
    minItems: props.minItems,
    maxItems: props.maxItems,
    // items will be filled in by schema-utils from field.itemTemplate
    items: {
      type: "object",
      properties: {}
    }
  }),
  fromJSONSchema: (prop, key, isRequired) => {
    if (prop.type !== "array" || !prop.items) {
      return null;
    }
    return {
      id: key,
      type: "array",
      props: {
        label: getLabel(prop, key),
        description: prop.description,
        required: isRequired,
        minItems: prop.minItems,
        maxItems: prop.maxItems
      },
      // itemTemplate will be filled in by schema-utils
      itemTemplate: []
    };
  }
};
const defaultComponents = [
  // Container types (must be before primitives to match object/array JSON Schema)
  objectFieldDefinition,
  arrayFieldDefinition,
  // Specific types first
  emailFieldDefinition,
  passwordFieldDefinition,
  urlFieldDefinition,
  phoneFieldDefinition,
  dateFieldDefinition,
  textareaFieldDefinition,
  switchFieldDefinition,
  radioFieldDefinition,
  selectFieldDefinition,
  checkboxFieldDefinition,
  numberFieldDefinition,
  // Generic fallback last
  textFieldDefinition
];
function getComponentByType(type, components = defaultComponents) {
  return components.find((c) => c.type === type);
}

export { arrayFieldDefinition, checkboxFieldDefinition, dateFieldDefinition, defaultComponents, emailFieldDefinition, getComponentByType, numberFieldDefinition, objectFieldDefinition, passwordFieldDefinition, phoneFieldDefinition, radioFieldDefinition, selectFieldDefinition, switchFieldDefinition, textFieldDefinition, textareaFieldDefinition, urlFieldDefinition };
