import { useEffect, useMemo, useState } from "react";
import { Button } from "@govoplan/core-webui";
import { Dialog } from "@govoplan/core-webui";
import { DismissibleAlert } from "@govoplan/core-webui";
import type { TemplateNamespace, TemplatePlaceholder, UndefinedPlaceholder } from "../utils/templatePlaceholders";

export type TemplateFieldOption = {
  name: string;
  label: string;
};

export function TemplateFieldChipList({
  namespace,
  fields,
  usedPlaceholders = [],
  empty,
  disabled = false,
  onInsert
}: {
  namespace: TemplateNamespace;
  fields: TemplateFieldOption[];
  usedPlaceholders?: TemplatePlaceholder[];
  empty: string;
  disabled?: boolean;
  onInsert: (namespace: TemplateNamespace, name: string) => void;
}) {
  if (fields.length === 0) return <p className="muted">{empty}</p>;
  return (
    <div className="field-chip-list">
      {fields.map((field) => {
        const used = usedPlaceholders.some((placeholder) => placeholder.validNamespace && placeholder.namespace === namespace && placeholder.name === field.name);
        return (
          <button
            type="button"
            className={`field-chip field-chip-button ${used ? "used" : ""}`}
            key={`${namespace}:${field.name}`}
            disabled={disabled}
            onClick={() => onInsert(namespace, field.name)}
          >
            <span className="field-chip-namespace">{namespace}</span><span title={field.label !== field.name ? field.label : undefined}>{field.name}</span>
          </button>
        );
      })}
    </div>
  );
}

export function UndefinedPlaceholderList({
  items,
  empty = "No undefined placeholders detected.",
  onSelect
}: {
  items: UndefinedPlaceholder[];
  empty?: string;
  onSelect: (item: UndefinedPlaceholder) => void;
}) {
  if (items.length === 0) return <p className="muted">{empty}</p>;
  return (
    <div className="field-chip-list">
      {items.map((item) => (
        <button
          type="button"
          className="field-chip field-chip-button undefined"
          key={`${item.raw}:${item.reason}`}
          onClick={() => onSelect(item)}
        >
          {item.display}
        </button>
      ))}
    </div>
  );
}

export function UndefinedPlaceholderDecisionDialog({
  field,
  contextLabel = "template",
  removeLabel = "Remove placeholder",
  localFields = [],
  globalFields = [],
  onCancel,
  onRemove,
  onReplace,
  onAddField,
  addDisabled = false
}: {
  field: UndefinedPlaceholder | null;
  contextLabel?: string;
  removeLabel?: string;
  localFields?: TemplateFieldOption[];
  globalFields?: TemplateFieldOption[];
  onCancel: () => void;
  onRemove: (field: UndefinedPlaceholder) => void;
  onReplace?: (field: UndefinedPlaceholder, namespace: TemplateNamespace, name: string) => void;
  onAddField: (field: UndefinedPlaceholder) => void;
  addDisabled?: boolean;
}) {
  const replacementOptions = useMemo(
    () => [
      ...localFields.map((item) => ({ namespace: "local" as const, ...item })),
      ...globalFields.map((item) => ({ namespace: "global" as const, ...item }))
    ],
    [globalFields, localFields]
  );
  const [replacement, setReplacement] = useState("");
  const firstReplacement = replacementOptions[0];
  const effectiveReplacement = replacement || (firstReplacement ? `${firstReplacement.namespace}:${firstReplacement.name}` : "");

  useEffect(() => {
    setReplacement(firstReplacement ? `${firstReplacement.namespace}:${firstReplacement.name}` : "");
  }, [field?.raw, firstReplacement?.namespace, firstReplacement?.name]);

  function replaceWithSelected() {
    if (!field || !onReplace || !effectiveReplacement) return;
    const separator = effectiveReplacement.indexOf(":");
    if (separator < 0) return;
    const namespace = effectiveReplacement.slice(0, separator) as TemplateNamespace;
    const name = effectiveReplacement.slice(separator + 1);
    onReplace(field, namespace, name);
  }

  return (
    <Dialog
      open={Boolean(field)}
      title="Undefined field reference"
      closeLabel="Return to editing"
      className="template-action-dialog"
      onClose={onCancel}
      footer={field ? (
        <>
          <Button onClick={onCancel}>Continue editing</Button>
          <Button onClick={() => onRemove(field)}>{removeLabel}</Button>
          {onReplace && replacementOptions.length > 0 && <Button onClick={replaceWithSelected}>Replace</Button>}
          <Button variant="primary" onClick={() => onAddField(field)} disabled={!field.name || field.reason === "invalid-namespace" || addDisabled}>Add field</Button>
        </>
      ) : undefined}
    >
      {field && (
        <>
          <p>The {contextLabel} uses <code>{`{{${field.raw}}}`}</code>, but it cannot be matched to a known field.</p>
          {field.reason === "invalid-namespace" && (
            <DismissibleAlert tone="warning">Use the namespace <code>global:</code> or <code>local:</code>.</DismissibleAlert>
          )}
          {field.reason === "missing-field" && (
            <p className="muted">You can add <strong>{field.name}</strong> as a campaign field, remove this placeholder, or continue editing.</p>
          )}
          {onReplace && replacementOptions.length > 0 && (
            <label className="template-replacement-field">
              <span>Replace by existing field</span>
              <select value={effectiveReplacement} onChange={(event) => setReplacement(event.target.value)}>
                {replacementOptions.map((option) => (
                  <option key={`${option.namespace}:${option.name}`} value={`${option.namespace}:${option.name}`}>
                    {option.namespace}:{option.label || option.name}
                  </option>
                ))}
              </select>
            </label>
          )}
        </>
      )}
    </Dialog>
  );
}
