import { ChevronDown, ChevronUp, Plus, Trash2 } from "lucide-react";
import { Input } from "@/components/ui/input";
import {
  createEmptyArrayItem,
  getFieldLabel,
  getValueAtPath,
  humanizeFieldLabel,
  isEmojiField,
  isImageIconField,
  isLongTextField,
  isPlainObject,
  isReservedContentKey,
  isUrlLikeField,
  pathToString,
  setValueAtPath,
  type ContentRecord,
} from "@/lib/contentFormUtils";
import { EmojiPickerField } from "./EmojiPickerField";
import { ImageIconField } from "./ImageIconField";

const formRow = "mb-4";
const labelCls = "block text-sm font-medium text-slate-700 mb-1.5";
const panelCls = "rounded-xl border border-slate-200 bg-slate-50/60 p-4 mb-4";
const subPanelCls = "rounded-lg border border-slate-200 bg-white p-3 mb-3";

type DynamicContentFormProps = {
  content: ContentRecord;
  onChange: (content: ContentRecord) => void;
  depth?: number;
  excludeKeys?: string[];
  fieldLabels?: Record<string, string>;
  reorderableArrays?: boolean;
};

function TextareaField({
  value,
  onChange,
  placeholder,
  rows = 3,
}: {
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  rows?: number;
}) {
  return (
    <textarea
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      rows={rows}
      className="flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[80px]"
    />
  );
}

function ScalarField({
  fieldKey,
  value,
  onChange,
}: {
  fieldKey: string;
  value: unknown;
  onChange: (value: unknown) => void;
}) {
  if (typeof value === "boolean") {
    return (
      <label className="inline-flex items-center gap-2 text-sm text-slate-700">
        <input
          type="checkbox"
          checked={value}
          onChange={(e) => onChange(e.target.checked)}
          className="rounded border-slate-300"
        />
        {value ? "Enabled" : "Disabled"}
      </label>
    );
  }

  if (typeof value === "number") {
    return (
      <Input
        type="number"
        value={Number.isFinite(value) ? String(value) : "0"}
        onChange={(e) => onChange(e.target.value === "" ? 0 : Number(e.target.value))}
      />
    );
  }

  const stringValue = typeof value === "string" ? value : value == null ? "" : String(value);

  if (isEmojiField(fieldKey, stringValue)) {
    return (
      <EmojiPickerField
        value={stringValue}
        onChange={(v) => onChange(v)}
        placeholder="Pick or type emoji"
      />
    );
  }

  if (isImageIconField(fieldKey, stringValue)) {
    return (
      <ImageIconField
        value={stringValue}
        onChange={(v) => onChange(v)}
        placeholder={isUrlLikeField(fieldKey) ? "https://… or pick an icon" : "Image URL or icon"}
      />
    );
  }

  const placeholder = isUrlLikeField(fieldKey) ? "https://… or /path/to/asset" : undefined;

  if (isLongTextField(fieldKey, stringValue)) {
    return <TextareaField value={stringValue} onChange={(v) => onChange(v)} placeholder={placeholder} />;
  }

  return <Input value={stringValue} onChange={(e) => onChange(e.target.value)} placeholder={placeholder} />;
}

function getArrayItemTitle(
  path: Array<string | number>,
  item: unknown,
  index: number,
  fallbackLabel: string
): string {
  if (path[path.length - 1] === "tabs" && isPlainObject(item)) {
    const name = typeof item.buttonLabel === "string" && item.buttonLabel.trim()
      ? item.buttonLabel
      : typeof item.title === "string" && item.title.trim()
        ? item.title
        : `Tab ${index + 1}`;
    return `Tab ${index + 1}: ${name}`;
  }
  return `${fallbackLabel} ${index + 1}`;
}

function ArrayField({
  path,
  label,
  value,
  content,
  onChange,
  depth,
  fieldLabels,
  reorderable = true,
}: {
  path: Array<string | number>;
  label: string;
  value: unknown[];
  content: ContentRecord;
  onChange: (content: ContentRecord) => void;
  depth: number;
  fieldLabels?: Record<string, string>;
  reorderable?: boolean;
}) {
  const inferTemplate = (): unknown => {
    const lastKey = path[path.length - 1];
    if (lastKey === "filters") {
      return { key: "", value: "" };
    }
    if (value.length > 0) return value[0];
    if (lastKey === "tabs") {
      return createEmptyArrayItem({
        key: `tab-${Date.now()}`,
        title: "New Tab",
        emoji: "✨",
        color: "valencia",
        desc: "",
        buttonLabel: "New Tab",
        iconSrc: "",
        position: { desktop: "top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2", mobileOrder: value.length },
        traitGroups: [],
        courseGroups: [],
      });
    }
    if (typeof lastKey === "string" && /tags|labels|lines/i.test(lastKey)) {
      return "";
    }
    return createEmptyArrayItem({});
  };

  const addItem = () => {
    const template = inferTemplate();
    const next = [...value, createEmptyArrayItem(template)];
    onChange(setValueAtPath(content, path, next));
  };

  const removeItem = (index: number) => {
    onChange(setValueAtPath(content, path, value.filter((_, i) => i !== index)));
  };

  const moveItem = (index: number, direction: -1 | 1) => {
    const target = index + direction;
    if (target < 0 || target >= value.length) return;
    const next = [...value];
    [next[index], next[target]] = [next[target], next[index]];
    onChange(setValueAtPath(content, path, next));
  };

  const isPrimitiveArray = value.every((item) => ["string", "number", "boolean"].includes(typeof item) || item == null);
  const arrayKey = path[path.length - 1];
  const addLabel =
    arrayKey === "tabs" ? "Add tab" : arrayKey === "filters" ? "Add filter" : "Add item";
  const emptyMessage =
    arrayKey === "filters" ? "No filters yet." : "No items yet.";

  return (
    <div className={depth === 0 ? formRow : subPanelCls}>
      <div className="flex items-center justify-between gap-2 mb-2">
        <p className="text-sm font-semibold text-slate-800">{label}</p>
        <button
          type="button"
          onClick={addItem}
          className="inline-flex items-center gap-1 text-xs font-medium text-slate-700 hover:text-slate-900"
        >
          <Plus size={14} /> {addLabel}
        </button>
      </div>

      {value.length === 0 ? (
        <p className="text-xs text-slate-500 mb-2">{emptyMessage}</p>
      ) : null}

      <div className="space-y-3">
        {value.map((item, index) => (
          <div key={`${pathToString(path)}-${index}`} className="rounded-lg border border-slate-200 bg-white p-3">
            <div className="flex items-center justify-between gap-2 mb-2">
              <p className="text-xs font-semibold uppercase tracking-wide text-slate-500">
                {getArrayItemTitle(path, item, index, label)}
              </p>
              <div className="flex items-center gap-2">
                {reorderable && value.length > 1 ? (
                  <>
                    <button
                      type="button"
                      disabled={index === 0}
                      onClick={() => moveItem(index, -1)}
                      className="p-1 text-slate-500 hover:text-slate-800 disabled:opacity-30"
                      title="Move up"
                    >
                      <ChevronUp size={14} />
                    </button>
                    <button
                      type="button"
                      disabled={index === value.length - 1}
                      onClick={() => moveItem(index, 1)}
                      className="p-1 text-slate-500 hover:text-slate-800 disabled:opacity-30"
                      title="Move down"
                    >
                      <ChevronDown size={14} />
                    </button>
                  </>
                ) : null}
                <button
                  type="button"
                  onClick={() => removeItem(index)}
                  className="inline-flex items-center gap-1 text-xs text-red-600 hover:text-red-700"
                >
                  <Trash2 size={14} /> Remove
                </button>
              </div>
            </div>

            {isPrimitiveArray ? (
              <ScalarField
                fieldKey={String(path[path.length - 1] ?? "item")}
                value={item}
                onChange={(next) => {
                  const updated = [...value];
                  updated[index] = next;
                  onChange(setValueAtPath(content, path, updated));
                }}
              />
            ) : (
              <DynamicContentFields
                content={content}
                onChange={onChange}
                path={[...path, index]}
                depth={depth + 1}
                fieldLabels={fieldLabels}
                reorderableArrays={reorderable}
              />
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

export function DynamicContentFields({
  content,
  onChange,
  path = [],
  depth = 0,
  excludeKeys = [],
  fieldLabels,
  reorderableArrays = true,
}: {
  content: ContentRecord;
  onChange: (content: ContentRecord) => void;
  path?: Array<string | number>;
  depth?: number;
  excludeKeys?: string[];
  fieldLabels?: Record<string, string>;
  reorderableArrays?: boolean;
}) {
  const rootLabels =
    fieldLabels ??
    (isPlainObject(content.__fieldLabels) ? (content.__fieldLabels as Record<string, string>) : undefined);

  const node = path.length === 0 ? content : getValueAtPath(content, path);
  if (!isPlainObject(node)) {
    return null;
  }

  const entries = Object.entries(node).filter(
    ([key]) => !isReservedContentKey(key) && !excludeKeys.includes(key)
  );

  return (
    <>
      {entries.map(([key, value]) => {
        const fieldPath = [...path, key];
        const label = getFieldLabel(key, rootLabels);

        if (Array.isArray(value)) {
          return (
            <ArrayField
              key={pathToString(fieldPath)}
              path={fieldPath}
              label={label}
              value={value}
              content={content}
              onChange={onChange}
              depth={depth}
              fieldLabels={rootLabels}
              reorderable={reorderableArrays}
            />
          );
        }

        if (isPlainObject(value)) {
          return (
            <div key={pathToString(fieldPath)} className={depth === 0 ? panelCls : subPanelCls}>
              <p className="text-sm font-semibold text-slate-800 mb-3">{label}</p>
              <DynamicContentFields
                content={content}
                onChange={onChange}
                path={fieldPath}
                depth={depth + 1}
                fieldLabels={rootLabels}
                reorderableArrays={reorderableArrays}
              />
            </div>
          );
        }

        return (
          <div key={pathToString(fieldPath)} className={formRow}>
            <label className={labelCls}>{label}</label>
            <ScalarField
              fieldKey={key}
              value={value}
              onChange={(next) => onChange(setValueAtPath(content, fieldPath, next))}
            />
          </div>
        );
      })}
    </>
  );
}

/** Schema-driven editor: renders inputs for every key in the content object tree. */
export function DynamicContentForm({
  content,
  onChange,
  depth = 0,
  excludeKeys,
  fieldLabels,
  reorderableArrays = true,
}: DynamicContentFormProps) {
  const keys = Object.keys(content).filter(
    (key) => !isReservedContentKey(key) && !(excludeKeys ?? []).includes(key)
  );

  if (keys.length === 0) {
    return <p className="text-sm text-slate-500">No editable fields in this component content yet.</p>;
  }

  return (
    <DynamicContentFields
      content={content}
      onChange={onChange}
      depth={depth}
      excludeKeys={excludeKeys}
      fieldLabels={fieldLabels}
      reorderableArrays={reorderableArrays}
    />
  );
}
