import React, { useState } from 'react';
import type { CBNode } from '../../types';
import { BLOCKS } from '../canvas/BlockPicker';
import { activeDrag } from '../canvas/CanvasNode';
import { WIDGET_REGISTRY } from '../../widgets/registry';

interface ElementEntry {
  type: string;
  label: string;
  icon: string;
  color: string;
  defaultNode: Partial<CBNode>;
}

interface ElementGroup {
  category: string;
  items: ElementEntry[];
}

const LAYOUT_ITEMS: ElementEntry[] = [
  { type: 'section',   label: 'Section',   icon: '⊞', color: '#8b5cf6', defaultNode: { type: 'section',   children: [], styles: {}, settings: {} } },
  { type: 'container', label: 'Container', icon: '□', color: '#3b82f6', defaultNode: { type: 'container', settings: { columns: 1 }, children: [], styles: {} } },
  { type: 'column',    label: 'Column',    icon: '⊟', color: '#10b981', defaultNode: { type: 'column',    children: [], styles: {}, settings: {} } },
];

const BASIC_TYPES     = ['heading', 'text', 'button', 'icon', 'divider', 'spacer', 'accordion', 'tabs-adv', 'counter', 'progress', 'badge', 'icon-list'];
// Navigation widgets live in their own tab so site-structure elements are
// not buried among the generic content blocks.
const NAVIGATION_TYPES = ['menu', 'adv-menu', 'breadcrumbs'];
const MEDIA_TYPES     = ['image', 'video', 'logo', 'maps', 'gallery', 'image-carousel'];
const WIDGET_TYPES    = ['form', 'html', 'shortcode'];
const MARKETING_TYPES = ['alert', 'testimonial', 'testimonials', 'pricing-table', 'feature-card', 'cta', 'stats-card'];
const CONTENT_TYPES   = ['faq', 'table', 'team-member', 'timeline'];

function blocksByTypes(types: string[]): ElementEntry[] {
  return types.flatMap((t) => {
    const found = BLOCKS.filter((b) => b.type === t);
    if (!found.length) return [];
    const b = found[0];
    return [{ type: b.type, label: b.label, icon: b.icon, color: b.color, defaultNode: b.defaultNode }];
  });
}

// Schema-driven registry widgets (non-bespoke) grouped by their palette group.
// This is what makes a new widget appear in the palette from its registry entry
// alone — no edit to this file per widget. Existing bespoke widgets are still
// listed explicitly in the *_TYPES arrays above (unchanged), so their grouping
// is byte-identical to before; only genuinely new registry widgets flow here.
// Types already placed by one of the hardcoded *_TYPES lists above. A widget
// is auto-grouped by its registry category ONLY if it isn't already listed
// there — keying off placement (not the `bespoke` flag) is what lets a bespoke
// widget in a brand-new category, e.g. WooCommerce's Products Grid, reach the
// palette. Keying off `!bespoke` instead both hid those widgets entirely and
// emitted a duplicate tab whenever a schema widget reused a hardcoded group
// name (Icon Box → a second "Basic").
const PLACED_TYPES = new Set<string>([
  ...LAYOUT_ITEMS.map((i) => i.type),
  ...BASIC_TYPES, ...NAVIGATION_TYPES, ...MEDIA_TYPES, ...MARKETING_TYPES,
  ...CONTENT_TYPES, ...WIDGET_TYPES,
]);

function schemaWidgetsByGroup(group: string): ElementEntry[] {
  return WIDGET_REGISTRY
    .filter((w) => !PLACED_TYPES.has(w.type) && w.category === group)
    .map((w) => ({ type: w.type, label: w.label, icon: w.icon, color: w.color, defaultNode: w.defaultNode }));
}

// Every distinct palette group used by a not-yet-placed widget, in registry
// order — so ANY new category surfaces its own tab automatically. Groups whose
// name collides with a hardcoded category are excluded here and merged into
// that existing group instead (see ELEMENT_GROUPS), so no tab is ever
// duplicated.
// Groups that ELEMENT_GROUPS builds explicitly below. Anything listed here is
// excluded from SCHEMA_GROUPS, otherwise the same category would be emitted
// twice and render as a duplicate tab.
const HARDCODED_GROUPS = new Set(['LAYOUT', 'BASIC', 'NAVIGATION', 'MEDIA', 'MARKETING', 'CONTENT', 'WIDGETS']);

const SCHEMA_GROUPS = Array.from(
  new Set(
    WIDGET_REGISTRY
      .filter((w) => !PLACED_TYPES.has(w.type))
      .map((w) => w.category)
  )
).filter((g) => !HARDCODED_GROUPS.has(g.toUpperCase()));

/** Unplaced registry widgets whose category matches a hardcoded group name.
 * They join that existing group instead of spawning a duplicate tab (e.g.
 * Icon Box, category 'Basic', joins BASIC). */
function extrasFor(hardcoded: string): ElementEntry[] {
  return WIDGET_REGISTRY
    .filter((w) => !PLACED_TYPES.has(w.type) && w.category.toUpperCase() === hardcoded)
    .map((w) => ({ type: w.type, label: w.label, icon: w.icon, color: w.color, defaultNode: w.defaultNode }));
}

const ELEMENT_GROUPS: ElementGroup[] = [
  { category: 'LAYOUT',    items: [...LAYOUT_ITEMS,                 ...extrasFor('LAYOUT')] },
  { category: 'BASIC',     items: [...blocksByTypes(BASIC_TYPES),     ...extrasFor('BASIC')] },
  { category: 'NAVIGATION', items: [...blocksByTypes(NAVIGATION_TYPES), ...extrasFor('NAVIGATION')] },
  { category: 'MEDIA',     items: [...blocksByTypes(MEDIA_TYPES),     ...extrasFor('MEDIA')] },
  { category: 'MARKETING', items: [...blocksByTypes(MARKETING_TYPES), ...extrasFor('MARKETING')] },
  { category: 'CONTENT',   items: [...blocksByTypes(CONTENT_TYPES),   ...extrasFor('CONTENT')] },
  { category: 'WIDGETS',   items: [...blocksByTypes(WIDGET_TYPES),    ...extrasFor('WIDGETS')] },
  ...SCHEMA_GROUPS.map((g) => ({ category: g.toUpperCase(), items: schemaWidgetsByGroup(g) })),
].filter((g) => g.items.length > 0);

const ALL_ITEMS = ELEMENT_GROUPS.flatMap((g) => g.items);

// The panel now shows category ACCORDIONS (like the reference design) instead of
// horizontal category tabs. The top row is a simple view switch.
const VIEW_TABS = ['ALL', 'FAVORITES', 'RECENT'] as const;
type Tab = (typeof VIEW_TABS)[number];

const FAVORITES_KEY = 'jalpiElementFavorites';
const RECENT_KEY    = 'jalpiElementRecent';

function loadList(key: string): string[] {
  try { const v = JSON.parse(localStorage.getItem(key) || '[]'); return Array.isArray(v) ? v : []; }
  catch { return []; }
}
function saveList(key: string, list: string[]) {
  try { localStorage.setItem(key, JSON.stringify(list.slice(0, 24))); } catch { /* ignore */ }
}

interface Props {
  onAdd: (defaultNode: Partial<CBNode>) => void;
  onClose: () => void;
  onOpenRevisions: () => void;
}

const SearchIcon = () => (
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <circle cx="11" cy="11" r="7"/><path d="m21 21-4.35-4.35"/>
  </svg>
);

const HistoryIcon = () => (
  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>
    <path d="M3 3v5h5"/><path d="M12 7v5l4 2"/>
  </svg>
);

const WPIcon = () => (
  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <path d="M12 2a10 10 0 1 0 0 20A10 10 0 0 0 12 2z"/>
    <path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>
  </svg>
);

const ChevronIcon = ({ open }: { open: boolean }) => (
  <svg
    className={`jalpi-elements-group__chevron${open ? ' is-open' : ''}`}
    width="14" height="14" viewBox="0 0 24 24" fill="none"
    stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"
  >
    <path d="m6 9 6 6 6-6"/>
  </svg>
);

const StarIcon = ({ filled }: { filled: boolean }) => (
  <svg width="12" height="12" viewBox="0 0 24 24"
    fill={filled ? 'currentColor' : 'none'} stroke="currentColor"
    strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <path d="M12 2 15.09 8.26 22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14l-5-4.87 6.91-1.01L12 2z"/>
  </svg>
);

declare const jalpiEditorConfig: { adminUrl: string };

function titleCase(cat: string): string {
  if (cat === 'WOOCOMMERCE') return 'WooCommerce';
  return cat.charAt(0) + cat.slice(1).toLowerCase();
}

export function ElementsPanel({ onAdd, onClose, onOpenRevisions }: Props) {
  const [search, setSearch]   = useState('');
  const [view, setView]       = useState<Tab>('ALL');
  const [favorites, setFavorites] = useState<string[]>(() => loadList(FAVORITES_KEY));
  const [recent, setRecent]       = useState<string[]>(() => loadList(RECENT_KEY));
  // Which accordion groups are collapsed (default: all open).
  const [collapsed, setCollapsed] = useState<Record<string, boolean>>({});

  const q = search.trim().toLowerCase();
  const searchResults = q
    ? ALL_ITEMS.filter((item) =>
        item.label.toLowerCase().includes(q) || item.type.toLowerCase().includes(q)
      )
    : null;

  const toggleGroup = (cat: string) =>
    setCollapsed((c) => ({ ...c, [cat]: !c[cat] }));

  const toggleFavorite = (type: string) =>
    setFavorites((f) => {
      const next = f.includes(type) ? f.filter((t) => t !== type) : [type, ...f];
      saveList(FAVORITES_KEY, next);
      return next;
    });

  const noteRecent = (type: string) =>
    setRecent((r) => {
      const next = [type, ...r.filter((t) => t !== type)];
      saveList(RECENT_KEY, next);
      return next;
    });

  const handleAdd = (item: ElementEntry) => {
    noteRecent(item.type);
    onAdd(item.defaultNode);
  };

  const byType = (type: string) => ALL_ITEMS.find((i) => i.type === type);

  // A reusable element card.
  const renderCard = (item: ElementEntry, keyPrefix: string) => (
    <button
      key={`${item.type}__${keyPrefix}`}
      className="jalpi-elements-item"
      style={{ '--el-color': item.color } as React.CSSProperties}
      draggable={item.type !== 'section'}
      onClick={() => handleAdd(item)}
      onDragStart={(e) => {
        activeDrag.newDef = item.defaultNode;
        e.dataTransfer.effectAllowed = 'copy';
        e.dataTransfer.setData('text/plain', item.type);
        (e.currentTarget as HTMLElement).classList.add('jalpi-elements-item--dragging');
      }}
      onDragEnd={(e) => {
        activeDrag.newDef = null;
        (e.currentTarget as HTMLElement).classList.remove('jalpi-elements-item--dragging');
      }}
      title={item.label}
    >
      <span
        className={`jalpi-elements-item__fav${favorites.includes(item.type) ? ' is-fav' : ''}`}
        role="button"
        title={favorites.includes(item.type) ? 'Remove from favorites' : 'Add to favorites'}
        onClick={(e) => { e.stopPropagation(); toggleFavorite(item.type); }}
      >
        <StarIcon filled={favorites.includes(item.type)} />
      </span>
      <span className="jalpi-elements-item__icon">{item.icon}</span>
      <span className="jalpi-elements-item__label">{item.label}</span>
    </button>
  );

  const renderGrid = (items: ElementEntry[], keyPrefix: string) => (
    <div className="jalpi-elements-group__grid">
      {items.map((item) => renderCard(item, keyPrefix))}
    </div>
  );

  // Flat lists for Favorites / Recent views.
  const favItems    = favorites.map(byType).filter(Boolean) as ElementEntry[];
  const recentItems = recent.map(byType).filter(Boolean) as ElementEntry[];

  return (
    <div className="jalpi-elements-panel">
      {/* Header */}
      <div className="jalpi-elements-panel__header">
        <span className="jalpi-elements-panel__title">Elements</span>
        <button className="jalpi-elements-panel__close" onClick={onClose} title="Close panel">
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
            <path d="M18 6 6 18M6 6l12 12"/>
          </svg>
        </button>
      </div>

      {/* Search */}
      <div className="jalpi-elements-panel__search">
        <span className="jalpi-elements-panel__search-icon"><SearchIcon /></span>
        <input
          type="text"
          className="jalpi-elements-panel__search-input"
          placeholder="Search elements..."
          value={search}
          onChange={(e) => setSearch(e.target.value)}
        />
        {search && (
          <button className="jalpi-elements-panel__search-clear" onClick={() => setSearch('')} title="Clear">
            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
              <path d="M18 6 6 18M6 6l12 12"/>
            </svg>
          </button>
        )}
      </div>

      {/* View tabs: All / Favorites / Recent */}
      {!searchResults && (
        <div className="jalpi-elements-panel__views">
          {VIEW_TABS.map((tab) => (
            <button
              key={tab}
              className={`jalpi-elements-view${view === tab ? ' is-active' : ''}`}
              onClick={() => setView(tab)}
            >
              {tab === 'FAVORITES' && <StarIcon filled={view === 'FAVORITES'} />}
              {tab === 'ALL' ? 'All' : tab === 'FAVORITES' ? 'Favorites' : 'Recent'}
            </button>
          ))}
        </div>
      )}

      {/* Body */}
      <div className="jalpi-elements-panel__list">
        {searchResults ? (
          searchResults.length === 0
            ? <div className="jalpi-elements-panel__empty">No elements found</div>
            : renderGrid(searchResults, 'search')
        ) : view === 'FAVORITES' ? (
          favItems.length === 0
            ? <div className="jalpi-elements-panel__empty">No favorites yet — tap the ★ on any element.</div>
            : renderGrid(favItems, 'fav')
        ) : view === 'RECENT' ? (
          recentItems.length === 0
            ? <div className="jalpi-elements-panel__empty">No recent elements yet.</div>
            : renderGrid(recentItems, 'recent')
        ) : (
          // ALL view → collapsible category accordions
          ELEMENT_GROUPS.map((group) => {
            const isCollapsed = !!collapsed[group.category];
            return (
              <div className="jalpi-elements-group" key={group.category}>
                <button
                  className="jalpi-elements-group__head"
                  onClick={() => toggleGroup(group.category)}
                  aria-expanded={!isCollapsed}
                >
                  <span className="jalpi-elements-group__title">{titleCase(group.category)}</span>
                  <ChevronIcon open={!isCollapsed} />
                </button>
                {!isCollapsed && renderGrid(group.items, group.category)}
              </div>
            );
          })
        )}
      </div>

      {/* Footer toolbar */}
      <div className="jalpi-elements-panel__footer">
        <button className="jalpi-elements-panel__footer-btn" onClick={onOpenRevisions} title="Revision History">
          <HistoryIcon />
          <span>History</span>
        </button>
        <a className="jalpi-elements-panel__footer-btn" href={jalpiEditorConfig.adminUrl} title="Back to WordPress">
          <WPIcon />
          <span>WP Admin</span>
        </a>
      </div>
    </div>
  );
}
