import Fuse from "fuse.js";
import { Plus, Search } from "lucide-react";
import { useMemo, useState } from "react";

const shaderSearchOptions = {
  threshold: 0.38,
  ignoreLocation: true,
  minMatchCharLength: 2,
  keys: [
    { name: "name", weight: 0.45 },
    { name: "id", weight: 0.25 },
    { name: "category", weight: 0.15 },
    { name: "description", weight: 0.1 },
    { name: "error", weight: 0.05 },
  ],
};

function shaderSummary(shader) {
  if (!shader) {
    return "Search available shaders";
  }

  if (shader.available === false) {
    return shader.error || "Shader is unavailable";
  }

  return shader.description || "No description";
}

function ShaderOptionContent({ shader }) {
  return (
    <>
      <span className="shader-picker__option-head">
        <span className="shader-picker__name">{shader.name}</span>
        {shader.available === false ? <span className="shader-picker__category shader-picker__category--error">Error</span> : null}
        {shader.available !== false && shader.category ? <span className="shader-picker__category">{shader.category}</span> : null}
      </span>
      <span className="shader-picker__meta">{shaderSummary(shader)}</span>
    </>
  );
}

export function ShaderPicker({ id, label = "Shader", shaders, onAdd }) {
  const [query, setQuery] = useState("");

  const shaderSearch = useMemo(
    () => new Fuse(shaders, shaderSearchOptions),
    [shaders],
  );

  const filteredShaders = useMemo(
    () => {
      const normalizedQuery = query.trim();
      if (!normalizedQuery) {
        return shaders;
      }

      return shaderSearch.search(normalizedQuery).map((result) => result.item);
    },
    [query, shaderSearch, shaders],
  );

  return (
    <div className="shader-picker">
      <div className="shader-picker__topline">
        <label id={`${id}-label`}>{label}</label>
      </div>

      <div className="shader-picker__popover">
        <div className="shader-picker__search">
          <Search size={16} strokeWidth={1.75} aria-hidden="true" />
          <input
            id={`${id}-search`}
            type="text"
            value={query}
            placeholder="Search shaders"
            onChange={(event) => setQuery(event.target.value)}
          />
        </div>

        <div className="shader-picker__list" role="list" aria-labelledby={`${id}-label`}>
          {filteredShaders.length > 0 ? (
            filteredShaders.map((shader) => (
              <div
                key={shader.id}
                className={`shader-picker__option${shader.available === false ? " shader-picker__option--unavailable" : ""}`}
                role="listitem"
              >
                <span className="shader-picker__option-copy">
                  <ShaderOptionContent shader={shader} />
                </span>
                <button
                  type="button"
                  className="icon-button shader-picker__add"
                  title={`Add ${shader.name}`}
                  aria-label={`Add ${shader.name}`}
                  disabled={shader.available === false}
                  onClick={() => {
                    if (shader.available === false) {
                      return;
                    }
                    onAdd(shader.id);
                    setQuery("");
                  }}
                >
                  <Plus size={16} strokeWidth={1.9} />
                </button>
              </div>
            ))
          ) : (
            <div className="shader-picker__empty">No shaders found</div>
          )}
        </div>
      </div>
    </div>
  );
}
