import { jsx } from 'react/jsx-runtime';
import { useMemo, useState, useEffect, useCallback } from 'react';
import { CONFIG, LAYOUT_GROUPS, LAYOUT_ORDER } from './config.mjs';
import { ClassNameGroupControl } from './classname-group-control.mjs';
import { cn } from '../../../../../lib/utils.mjs';
import { isTailwindClass } from './helpers.mjs';

function ClassNameItemControl({ value, onChange }) {
  const parsed = useMemo(() => {
    if (value) {
      const tokens = value.trim().split(/\s+/);
      const parsedState = Object.entries(CONFIG).reduce(
        (acc, [key, config]) => {
          const parsed2 = tokens.filter((token) => isTailwindClass(config.possibleTypes.filter((type) => type !== null), token));
          if (parsed2.length > 0) {
            acc[key] = config.multiple ? parsed2 : parsed2[0];
          }
          return acc;
        },
        Object.fromEntries(Object.keys(CONFIG).map((k) => [k, null]))
      );
      const initialSelected = {};
      LAYOUT_GROUPS.forEach((group) => {
        let found = false;
        group.keys.forEach((key) => {
          if (parsedState[key]) {
            if (!found) {
              found = true;
              initialSelected[group.label] = key;
            } else {
              parsedState[key] = null;
            }
          }
        });
        if (!found && group.keys[0]) {
          initialSelected[group.label] = group.keys[0];
        }
      });
      const handledTokens = new Set(
        Object.values(parsedState).flatMap(
          (v) => Array.isArray(v) ? v : v ? [v] : []
        )
      );
      const unhandledTokens = tokens.filter(
        (token) => !handledTokens.has(token)
      );
      return {
        parsedState,
        unhandledTokens,
        initialSelected
      };
    } else {
      const initialSelected = {};
      LAYOUT_GROUPS.forEach((group) => {
        if (group.keys[0]) {
          initialSelected[group.label] = group.keys[0];
        }
      });
      return {
        parsedState: {},
        unhandledTokens: [],
        initialSelected
      };
    }
  }, [value]);
  const [state, setState] = useState(parsed.parsedState);
  const [unhandled, setUnhandled] = useState(parsed.unhandledTokens);
  const [selectedKeys, setSelectedKeys] = useState(parsed.initialSelected);
  useEffect(() => {
    const stateChanged = JSON.stringify(state) !== JSON.stringify(parsed.parsedState);
    const unhandledChanged = JSON.stringify(unhandled) !== JSON.stringify(parsed.unhandledTokens);
    const selectedChanged = JSON.stringify(selectedKeys) !== JSON.stringify(parsed.initialSelected);
    if (stateChanged) setState(parsed.parsedState);
    if (unhandledChanged) setUnhandled(parsed.unhandledTokens);
    if (selectedChanged) setSelectedKeys(parsed.initialSelected);
  }, [parsed]);
  const buildClassString = (customState = state, customUnhandled = unhandled) => {
    const classes = [];
    for (const key in customState) {
      const value2 = customState[key];
      if (value2) {
        if (Array.isArray(value2)) {
          classes.push(...value2);
        } else {
          classes.push(value2);
        }
      }
    }
    return [...classes, ...customUnhandled].join(" ").trim();
  };
  const handleStateChange = useCallback((key, value2) => {
    setState((prev) => {
      const newState = { ...prev, [key]: value2 };
      const group = LAYOUT_GROUPS.find((g) => g.keys.includes(key));
      if (group) {
        setSelectedKeys((prevSel) => ({
          ...prevSel,
          [group.label]: key
        }));
        group.keys.forEach((k) => {
          if (k !== key) newState[k] = null;
        });
        if (typeof group.clearState === "function") {
          const classesToClear = group.clearState(key, newState);
          setUnhandled(
            (prevUnhandled) => prevUnhandled.filter((token) => !classesToClear.includes(token))
          );
        }
      }
      const layoutOrderItemsInvisible = LAYOUT_ORDER.filter(
        (item) => item.isVisible && !item.isVisible(newState)
      );
      layoutOrderItemsInvisible.forEach((item) => {
        if (item.type === "item") {
          newState[item.key] = null;
        } else if (item.type === "group") {
          const group2 = LAYOUT_GROUPS.find((g) => g.label === item.label);
          if (group2) {
            group2.keys.forEach((key2) => {
              newState[key2] = null;
            });
          }
        }
      });
      return newState;
    });
  }, []);
  const createChangeHandler = useCallback(
    (key) => (value2) => handleStateChange(key, value2),
    [handleStateChange]
  );
  const handleGroupKeySelect = (groupLabel, key) => {
    setSelectedKeys((prev) => ({
      ...prev,
      [groupLabel]: key
    }));
    const group = LAYOUT_GROUPS.find((g) => g.label === groupLabel);
    if (group) {
      let classesToClear = [];
      setState((prevState) => {
        const newState = { ...prevState };
        if (typeof group.clearState === "function") {
          classesToClear = group.clearState(key, newState);
        }
        for (const k of group.keys) {
          if (k !== key) {
            const config = CONFIG[k];
            if (!config) continue;
            if (config.multiple && Array.isArray(newState[k])) {
              newState[k] = newState[k].filter(
                (v) => !classesToClear.includes(v)
              );
              if (Array.isArray(newState[k]) && newState[k]?.length === 0)
                newState[k] = null;
            } else if (classesToClear.includes(newState[k])) {
              newState[k] = null;
            }
          }
        }
        setUnhandled(
          (prevUnhandled) => prevUnhandled.filter((token) => !classesToClear.includes(token))
        );
        if (!newState[key]) newState[key] = null;
        return newState;
      });
    }
  };
  useEffect(() => {
    const classString = buildClassString(state, unhandled);
    if (onChange) onChange(classString);
  }, [state, unhandled]);
  return /* @__PURE__ */ jsx("div", { className: "w-full", "data-testid": "classname-item-control", children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-y-1 px-4 pt-2 pb-4", children: LAYOUT_ORDER.map((entry) => {
    if (entry.type === "group") {
      const group = LAYOUT_GROUPS.find((g) => g.label === entry.label);
      if (!group) return null;
      const keys = group.keys.map(String);
      const selectedKey = selectedKeys[group.label] || keys[0];
      if (entry.isVisible && !entry.isVisible(state)) return null;
      if (!selectedKey) return null;
      const groupConfig = CONFIG[selectedKey];
      if (!groupConfig) return null;
      return /* @__PURE__ */ jsx("div", { className: cn("w-full", entry.className), "data-testid": `group-${group.label.toLowerCase().replace(/\s+/g, "-")}`, children: /* @__PURE__ */ jsx(
        ClassNameGroupControl,
        {
          groupConfig,
          group,
          state,
          handleStateChange,
          handleGroupKeySelect,
          selectedKey
        }
      ) }, group.label);
    } else if (entry.type === "item") {
      if (entry.isVisible && !entry.isVisible(state)) return null;
      const configKey = entry.key;
      const ungroupedConfig = CONFIG[configKey];
      if (!ungroupedConfig) return null;
      return /* @__PURE__ */ jsx("div", { className: cn("w-full", entry.className), "data-testid": `item-${configKey}`, children: /* @__PURE__ */ jsx(
        ungroupedConfig.component,
        {
          ...ungroupedConfig,
          ..."multiple" in ungroupedConfig ? { multiple: ungroupedConfig.multiple } : {},
          value: state[configKey],
          onChange: createChangeHandler(configKey)
        }
      ) }, configKey);
    }
    return null;
  }) }) });
}

export { ClassNameItemControl };
