import React, { useState, useEffect, useCallback, useRef } from "react";
import { __, sprintf } from "@wordpress/i18n";
import {
  DndContext,
  KeyboardSensor,
  PointerSensor,
  closestCenter,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import {
  SortableContext,
  arrayMove,
  sortableKeyboardCoordinates,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import DefaultPageLayout from "@/components/DefaultPageLayout";
import { Skeleton } from "@libs/skeleton";
import { ToastContainer } from "@libs/toast";
import { useToast } from "@libs/toast/useToast";
import {
  GripVertical,
  Plus,
  Trash2,
  ChevronDown,
  ChevronUp,
  ToggleLeft,
  ToggleRight,
  Search,
  Loader2,
  Link,
  ShieldCheck,
} from "lucide-react";
import { buildUrl } from "@libs/url";

const getApiConfig = () => {
  const { env } = window.arraySubs || {};
  return {
    apiBaseUrl: `${env?.apiBaseUrl || ""}arraysubs/v1`,
    nonce: env?.nonce || "",
  };
};

const generateEndpoint = (label) => {
  if (!label) return "";
  return label
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-|-$/g, "")
    .substring(0, 40);
};

/**
 * Content search dropdown for selecting a page/CPT to link.
 */
const ContentSearchSelect = ({ value, contentTitle, onChange }) => {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState("");
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const wrapperRef = useRef(null);
  const debounceRef = useRef(null);

  useEffect(() => {
    const handleClickOutside = (e) => {
      if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
        setOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  const doSearch = useCallback(async (term) => {
    setLoading(true);
    const { apiBaseUrl, nonce } = getApiConfig();

    try {
      const url = buildUrl(`${apiBaseUrl}/myaccount-editor/search-content`, {
        search: term,
        page: 1,
      });
      const res = await fetch(url, {
        headers: { "X-WP-Nonce": nonce },
      });
      const data = await res.json();
      setResults(data.content?.results || []);
    } catch {
      setResults([]);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!open) return;
    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => doSearch(search), 300);
    return () => clearTimeout(debounceRef.current);
  }, [search, open, doSearch]);

  return (
    <div className="arraysubs-mae-content-search" ref={wrapperRef}>
      <button
        type="button"
        className="arraysubs-mae-content-search__trigger"
        onClick={() => setOpen(!open)}
      >
        <Link size={14} />
        <span>
          {value
            ? contentTitle || `#${value}`
            : __("Select content...", "arraysubs")}
        </span>
        <ChevronDown size={14} />
      </button>

      {open && (
        <div className="arraysubs-mae-content-search__dropdown">
          <div className="arraysubs-mae-content-search__input-wrap">
            <Search size={14} />
            <input
              type="text"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              placeholder={__("Search pages, posts, CPTs...", "arraysubs")}
              autoFocus
            />
            {loading && <Loader2 size={14} className="spin" />}
          </div>
          <div className="arraysubs-mae-content-search__results">
            {results.length === 0 && !loading && (
              <div className="arraysubs-mae-content-search__empty">
                {__("No results found", "arraysubs")}
              </div>
            )}
            {results.map((item) => (
              <button
                key={item.id}
                type="button"
                className={`arraysubs-mae-content-search__item ${
                  value === item.id
                    ? "arraysubs-mae-content-search__item--selected"
                    : ""
                }`}
                onClick={() => {
                  onChange(item.id, item.title, item.post_type);
                  setOpen(false);
                }}
              >
                <span className="arraysubs-mae-content-search__item-title">
                  {item.title}
                </span>
                <span className="arraysubs-mae-content-search__item-type">
                  {item.type_label}
                </span>
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
};

/**
 * Single menu item row.
 */
const MenuItemRow = ({ item, index, onChange, onRemove }) => {
  const [expanded, setExpanded] = useState(false);
  const isCustom = item.type === "custom";
  const displayLabel = item.label
    ? item.label
    : isCustom
    ? __("Untitled custom item", "arraysubs")
    : item._original_label || __("Untitled item", "arraysubs");
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: item.id });
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  };

  const update = (key, val) => onChange(index, { ...item, [key]: val });

  return (
    <div
      ref={setNodeRef}
      style={style}
      className={`arraysubs-mae-item ${
        !item.enabled ? "arraysubs-mae-item--disabled" : ""
      } ${isCustom ? "arraysubs-mae-item--custom" : ""} ${
        isDragging ? "arraysubs-mae-item--dragging" : ""
      }`}
    >
      <div className="arraysubs-mae-item__header">
        <button
          type="button"
          className="arraysubs-mae-item__drag"
          title={__("Drag to reorder", "arraysubs")}
          {...attributes}
          {...listeners}
        >
          <GripVertical size={16} />
        </button>

        <span className="arraysubs-mae-item__label">{displayLabel}</span>

        <span className="arraysubs-mae-item__type-badge">
          {isCustom ? __("Custom", "arraysubs") : __("Default", "arraysubs")}
        </span>

        <span className="arraysubs-mae-item__actions">
          <button
            type="button"
            className="arraysubs-mae-item__toggle-btn"
            onClick={() => update("enabled", !item.enabled)}
            title={
              item.enabled
                ? __("Disable", "arraysubs")
                : __("Enable", "arraysubs")
            }
          >
            {item.enabled ? (
              <ToggleRight size={20} color="#2271b1" />
            ) : (
              <ToggleLeft size={20} color="#999" />
            )}
          </button>

          <button
            type="button"
            className="arraysubs-mae-item__expand-btn"
            onClick={() => setExpanded(!expanded)}
            title={
              expanded
                ? __("Collapse details", "arraysubs")
                : __("Expand details", "arraysubs")
            }
          >
            {expanded ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
          </button>

          {isCustom && (
            <button
              type="button"
              className="arraysubs-mae-item__remove-btn"
              onClick={() => onRemove(index)}
              title={__("Remove", "arraysubs")}
            >
              <Trash2 size={16} />
            </button>
          )}
        </span>
      </div>

      {isCustom && expanded && (
        <div className="arraysubs-mae-item__body">
          <div className="arraysubs-mae-item__row">
            <div className="arraysubs-mae-item__col">
              <label>{__("Menu Label", "arraysubs")}</label>
              <input
                type="text"
                value={item.label || ""}
                onChange={(e) => {
                  const newLabel = e.target.value;
                  const updates = { label: newLabel };
                  if (!item._endpointEdited) {
                    updates.endpoint = generateEndpoint(newLabel);
                  }
                  onChange(index, { ...item, ...updates });
                }}
                placeholder={__("Menu label", "arraysubs")}
                className="regular-text"
              />
            </div>
            <div className="arraysubs-mae-item__col">
              <label>{__("Endpoint Slug", "arraysubs")}</label>
              <input
                type="text"
                value={item.endpoint || ""}
                onChange={(e) =>
                  onChange(index, {
                    ...item,
                    endpoint: e.target.value
                      .toLowerCase()
                      .replace(/[^a-z0-9-]/g, ""),
                    _endpointEdited: true,
                  })
                }
                placeholder={__("my-custom-page", "arraysubs")}
                className="regular-text"
              />
              <span className="arraysubs-mae-item__hint">
                {__("URL slug used in /my-account/{endpoint}", "arraysubs")}
              </span>
            </div>
          </div>

          <div className="arraysubs-mae-item__row">
            <div className="arraysubs-mae-item__col">
              <label>{__("Linked Content", "arraysubs")}</label>
              <ContentSearchSelect
                value={item.content_id || 0}
                contentTitle={item._content_title || ""}
                onChange={(id, title, postType) =>
                  onChange(index, {
                    ...item,
                    content_id: id,
                    content_type: postType,
                    _content_title: title,
                  })
                }
              />
              <span className="arraysubs-mae-item__hint">
                {__(
                  "Select a page or post whose content will be shown inside My Account.",
                  "arraysubs",
                )}
              </span>
            </div>
            <div className="arraysubs-mae-item__col arraysubs-mae-item__col--checkbox">
              <label>
                <input
                  type="checkbox"
                  checked={!!item.prevent_direct_access}
                  onChange={(e) =>
                    update("prevent_direct_access", e.target.checked)
                  }
                />
                <ShieldCheck size={14} />
                {__("Prevent direct access", "arraysubs")}
              </label>
              <span className="arraysubs-mae-item__hint">
                {__(
                  "When enabled, visitors will be redirected to the My Account page instead of viewing this content at its original URL.",
                  "arraysubs",
                )}
              </span>
            </div>
          </div>
        </div>
      )}

      {!isCustom && expanded && (
        <div className="arraysubs-mae-item__body">
          <div className="arraysubs-mae-item__row">
            <div className="arraysubs-mae-item__col">
              <label>{__("Custom Label (optional)", "arraysubs")}</label>
              <input
                type="text"
                value={item.label || ""}
                onChange={(e) => update("label", e.target.value)}
                placeholder={item._original_label || item.label}
                className="regular-text"
              />
              <span className="arraysubs-mae-item__hint">
                {__("Leave empty to keep the default label.", "arraysubs")}
              </span>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

/**
 * My Account Editor Page.
 */
const MyAccountEditor = () => {
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [items, setItems] = useState([]);
  const [menuItemsEnabled, setMenuItemsEnabled] = useState(true);
  const { toasts, showToast, removeToast } = useToast();
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 6,
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );

  const loadConfig = useCallback(async () => {
    setLoading(true);
    const { apiBaseUrl, nonce } = getApiConfig();

    try {
      // Load saved config and defaults in parallel.
      const [configRes, defaultsRes] = await Promise.all([
        fetch(buildUrl(`${apiBaseUrl}/myaccount-editor/config`), {
          headers: { "X-WP-Nonce": nonce },
        }),
        fetch(buildUrl(`${apiBaseUrl}/myaccount-editor/defaults`), {
          headers: { "X-WP-Nonce": nonce },
        }),
      ]);

      const configData = await configRes.json();
      const defaultsData = await defaultsRes.json();

      const savedConfig = Array.isArray(configData.content)
        ? { items: configData.content, menu_items_enabled: true }
        : configData.content || {};
      const savedItems = savedConfig.items || [];
      const defaults = defaultsData.content || [];

      setMenuItemsEnabled(savedConfig.menu_items_enabled ?? true);

      if (savedItems.length > 0) {
        // Merge: keep saved items but ensure new default items are appended.
        const savedIds = savedItems.map((i) => i.id);
        const merged = [...savedItems];

        defaults.forEach((d) => {
          if (!savedIds.includes(d.id)) {
            merged.push(d);
          }
        });

        setItems(merged);
      } else {
        setItems(defaults);
      }
    } catch (err) {
      showToast(
        err.message || __("Failed to load configuration", "arraysubs"),
        "error",
      );
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    loadConfig();
  }, [loadConfig]);

  const handleSave = async () => {
    if (menuItemsEnabled) {
      // Validate custom items.
      const customItems = items.filter((i) => i.type === "custom");
      const invalidCustom = customItems.filter(
        (i) => !i.endpoint || !i.label || !i.content_id,
      );
      const reservedEndpoints = items
        .filter((i) => i.type !== "custom")
        .map((i) => i.id);

      if (invalidCustom.length > 0) {
        showToast(
          __(
            "All custom items must have a label, endpoint slug, and linked content.",
            "arraysubs",
          ),
          "error",
        );
        return;
      }

      // Check for duplicate endpoints.
      const endpoints = customItems.map((i) => i.endpoint);
      if (new Set(endpoints).size !== endpoints.length) {
        showToast(
          __("Custom endpoint slugs must be unique.", "arraysubs"),
          "error",
        );
        return;
      }

      const conflictingEndpoint = endpoints.find((endpoint) =>
        reservedEndpoints.includes(endpoint),
      );

      if (conflictingEndpoint) {
        showToast(
          sprintf(
            __(
              'The endpoint "%s" is already used by WooCommerce or another plugin.',
              "arraysubs",
            ),
            conflictingEndpoint,
          ),
          "error",
        );
        return;
      }
    }

    setSaving(true);
    const { apiBaseUrl, nonce } = getApiConfig();

    try {
      const cleanedItems = items.map((item, idx) => {
        const cleaned = { ...item, position: idx };
        delete cleaned._endpointEdited;
        delete cleaned._original_label;
        delete cleaned._content_title;
        return cleaned;
      });

      const res = await fetch(
        buildUrl(`${apiBaseUrl}/myaccount-editor/config`),
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "X-WP-Nonce": nonce,
          },
          body: JSON.stringify({
            items: cleanedItems,
            menu_items_enabled: menuItemsEnabled,
          }),
        },
      );

      const data = await res.json();

      if (res.ok && data.content) {
        setItems(data.content.items || []);
        setMenuItemsEnabled(
          data.content.menu_items_enabled ?? menuItemsEnabled,
        );
        showToast(__("Configuration saved!", "arraysubs"), "success");
      } else {
        showToast(data.message || __("Failed to save", "arraysubs"), "error");
      }
    } catch (err) {
      showToast(err.message || __("Failed to save", "arraysubs"), "error");
    } finally {
      setSaving(false);
    }
  };

  const addCustomItem = () => {
    setItems([
      ...items,
      {
        id: `custom-${Date.now()}`,
        label: "",
        type: "custom",
        enabled: true,
        endpoint: "",
        content_id: 0,
        content_type: "page",
        prevent_direct_access: false,
      },
    ]);
  };

  const updateItem = (index, updated) => {
    const copy = [...items];
    copy[index] = updated;
    setItems(copy);
  };

  const removeItem = (index) => {
    setItems(items.filter((_, i) => i !== index));
  };

  const handleDragEnd = ({ active, over }) => {
    if (!over || active.id === over.id) {
      return;
    }

    setItems((currentItems) => {
      const oldIndex = currentItems.findIndex((item) => item.id === active.id);
      const newIndex = currentItems.findIndex((item) => item.id === over.id);

      if (oldIndex < 0 || newIndex < 0) {
        return currentItems;
      }

      return arrayMove(currentItems, oldIndex, newIndex);
    });
  };

  if (loading) {
    return (
      <DefaultPageLayout title={__("My Account Editor", "arraysubs")}>
        <Skeleton variant="rectangle" width="100%" height={400} />
      </DefaultPageLayout>
    );
  }

  return (
    <DefaultPageLayout
      title={__("My Account Editor", "arraysubs")}
      subtitle={__(
        "Customize the WooCommerce My Account navigation — reorder items, add linked pages, and control access.",
        "arraysubs",
      )}
    >
      <div className="arraysubs-card">
        <h3 className="arraysubs-card__title">
          {__("Menu Items", "arraysubs")}
        </h3>
        <p className="arraysubs-card__description">
          {__(
            "Use the drag handle to reorder items, toggle visibility, or add custom pages that appear as My Account tabs.",
            "arraysubs",
          )}
        </p>

        <label className="arraysubs-pf-avatar-settings__toggle">
          <input
            type="checkbox"
            checked={menuItemsEnabled}
            onChange={(e) => setMenuItemsEnabled(e.target.checked)}
          />
          {__("Enable My Account menu items customization", "arraysubs")}
        </label>

        {!menuItemsEnabled ? (
          <div className="arraysubs-mae-empty">
            <p>
              {__(
                "My Account menu item customization is currently disabled. Your saved menu configuration is preserved and will start applying again when you re-enable this toggle.",
                "arraysubs",
              )}
            </p>
          </div>
        ) : items.length === 0 ? (
          <div className="arraysubs-mae-empty">
            <p>
              {__(
                "No menu items configured. Save to load defaults from WooCommerce, or add a custom item.",
                "arraysubs",
              )}
            </p>
          </div>
        ) : (
          <DndContext
            sensors={sensors}
            collisionDetection={closestCenter}
            onDragEnd={handleDragEnd}
          >
            <SortableContext
              items={items.map((item) => item.id)}
              strategy={verticalListSortingStrategy}
            >
              <div className="arraysubs-mae-items-list">
                {items.map((item, index) => (
                  <MenuItemRow
                    key={item.id}
                    item={item}
                    index={index}
                    onChange={updateItem}
                    onRemove={removeItem}
                  />
                ))}
              </div>
            </SortableContext>
          </DndContext>
        )}

        {menuItemsEnabled && (
          <button
            type="button"
            className="button arraysubs-mae-add-btn"
            onClick={addCustomItem}
          >
            <Plus size={16} /> {__("Add Custom Item", "arraysubs")}
          </button>
        )}
      </div>

      {menuItemsEnabled && (
        <div className="arraysubs-card arraysubs-mae-info">
          <h3 className="arraysubs-card__title">
            {__("How It Works", "arraysubs")}
          </h3>
          <ul>
            <li>
              {__(
                "Default items come from WooCommerce and other plugins. You can reorder and hide them.",
                "arraysubs",
              )}
            </li>
            <li>
              {__(
                "Custom items link a published page or other content as a new My Account tab.",
                "arraysubs",
              )}
            </li>
            <li>
              {__(
                "The linked content renders with full builder support (Gutenberg, Elementor, Bricks).",
                "arraysubs",
              )}
            </li>
            <li>
              {__(
                'Enable "Prevent direct access" to redirect visitors from the original URL to the My Account version.',
                "arraysubs",
              )}
            </li>
            <li>
              {__(
                "After saving, permalink settings may need a flush. Visit Settings > Permalinks once if links don't work immediately.",
                "arraysubs",
              )}
            </li>
          </ul>
        </div>
      )}

      <div className="arraysubs-settings-actions arraysubs-bottom-fixed-actions">
        <div>
          <button
            type="button"
            className="button button-primary"
            onClick={handleSave}
            disabled={saving}
          >
            {saving
              ? __("Saving...", "arraysubs")
              : __("Save Configuration", "arraysubs")}
          </button>
        </div>
      </div>

      <ToastContainer toasts={toasts} removeToast={removeToast} />
    </DefaultPageLayout>
  );
};

export default MyAccountEditor;
