import React, { useCallback } from 'react';
import { useEditor } from '@craftjs/core';
import {
  SPACING_PRESETS,
  SHADOW_PRESETS,
} from '../../../constants/presets';
import {
  StylePanelProps,
  SectionLabel,
  PresetButtonGrid,
  CollapsibleSection,
  ColorPickerField,
  navColorFields,
  btnActiveStyle,
  labelStyle,
  inputStyle,
  smallInputStyle,
  sectionGap,
  useNodeProp,
  SpacingControl,
  BorderControl,
  BorderValue,
  buildBorderShorthand,
  AnimationControl,
  VisibilityControl,
} from './shared';
import { AssetPicker } from '../../../ui/AssetPicker';
import { usePages } from '../../../state/PageContext';
import { PageData } from '../../../types';

/* ---------- Link-to-page helpers (F1/F2: link picker + Sync with Pages) ----------
   Mirrors the export convention used elsewhere: the first page is always the
   landing page and publishes to '/', every other page publishes to '/{slug}'.
   See PageContext.tsx's uniqueSlug/slugify and the landing-page-lock comment
   in renamePage() for why index 0 is special-cased this way. */
export function pageHref(page: PageData, index: number): string {
  return index === 0 ? '/' : `/${page.slug}`;
}

type LinkMode = 'page' | 'url' | 'anchor' | 'tel' | 'mailto';

function detectLinkMode(value: string, pageHrefs: string[]): LinkMode {
  const v = value || '';
  if (pageHrefs.includes(v)) return 'page';
  if (v.startsWith('#')) return 'anchor';
  if (v.startsWith('tel:')) return 'tel';
  if (v.startsWith('mailto:')) return 'mailto';
  return 'url';
}

/* ---------- LinkPicker ----------
   Reused for every link-href field in this panel (standalone Logo's href,
   Navbar's logoUrl, and each Navbar/Menu link item's href): a dropdown of
   the site's PAGES (read-only via usePages() -- PageContext itself is
   Wave-2's territory) plus manual URL / #anchor / tel: / mailto: entry.
   safeUrl (in toHtml) already allows tel:/mailto: schemes, so no export-side
   change is needed for those. */
interface LinkPickerProps {
  value: string;
  onChange: (value: string) => void;
}
export const LinkPicker: React.FC<LinkPickerProps> = ({ value, onChange }) => {
  const { pages } = usePages();
  const pageOptions = pages.map((p, i) => ({ id: p.id, name: p.name, href: pageHref(p, i) }));
  const mode = detectLinkMode(value || '', pageOptions.map((p) => p.href));

  const switchMode = (next: LinkMode) => {
    if (next === mode) return;
    if (next === 'page') onChange(pageOptions[0]?.href || '/');
    else if (next === 'anchor') onChange('#');
    else if (next === 'tel') onChange('tel:');
    else if (next === 'mailto') onChange('mailto:');
    else onChange('');
  };

  return (
    <div style={sectionGap} data-testid="link-picker">
      <label style={labelStyle}>Link</label>
      <select
        value={mode}
        onChange={(e) => switchMode(e.target.value as LinkMode)}
        style={{ ...inputStyle, marginBottom: 4, cursor: 'pointer' }}
      >
        <option value="page">Page</option>
        <option value="url">Custom URL</option>
        <option value="anchor">Anchor (#section)</option>
        <option value="tel">Phone (tel:)</option>
        <option value="mailto">Email (mailto:)</option>
      </select>
      {mode === 'page' && (
        pageOptions.length > 0 ? (
          <select value={value} onChange={(e) => onChange(e.target.value)} style={inputStyle}>
            {pageOptions.map((p) => (
              <option key={p.id} value={p.href}>{p.name}</option>
            ))}
          </select>
        ) : (
          <div style={{ fontSize: 11, color: '#71717a' }}>No pages yet</div>
        )
      )}
      {mode === 'anchor' && (
        <input
          type="text"
          value={value || ''}
          onChange={(e) => onChange(e.target.value.startsWith('#') ? e.target.value : `#${e.target.value}`)}
          placeholder="#section-id"
          style={inputStyle}
        />
      )}
      {mode === 'tel' && (
        <input
          type="text"
          value={(value || '').replace(/^tel:/, '')}
          onChange={(e) => onChange(`tel:${e.target.value}`)}
          placeholder="+15551234567"
          style={inputStyle}
        />
      )}
      {mode === 'mailto' && (
        <input
          type="text"
          value={(value || '').replace(/^mailto:/, '')}
          onChange={(e) => onChange(`mailto:${e.target.value}`)}
          placeholder="name@example.com"
          style={inputStyle}
        />
      )}
      {mode === 'url' && (
        <input
          type="text"
          value={value || ''}
          onChange={(e) => onChange(e.target.value)}
          placeholder="https://example.com or /page"
          style={inputStyle}
        />
      )}
    </div>
  );
};

/* Parses a `border` shorthand ("2px solid #hex" / "none") back into the
   { width, style, color } shape BorderControl edits. */
function parseBorderShorthand(v: string | undefined): BorderValue {
  if (!v || v === 'none') return { width: '', style: 'none', color: '#000000' };
  const m = v.trim().match(/^(\S+)\s+(\S+)\s+(.+)$/);
  if (!m) return { width: '', style: 'none', color: '#000000' };
  return { width: m[1], style: m[2], color: m[3] };
}

function capitalize(s: string): string {
  return s.charAt(0).toUpperCase() + s.slice(1);
}

/* ---------- NAV / MENU / LOGO / FOOTER ---------- */
export const NavStylePanel: React.FC<StylePanelProps> = ({ selectedId, nodeProps }) => {
  const { actions } = useEditor();
  const { setProp, setPropStyle } = useNodeProp(selectedId);
  const { pages } = usePages();

  const links: any[] = nodeProps.links || [];

  const updateLink = useCallback((index: number, field: string, value: any) => {
    actions.setProp(selectedId, (props: any) => {
      const updated = [...(props.links || [])];
      updated[index] = { ...updated[index], [field]: value };
      props.links = updated;
    });
  }, [actions, selectedId]);

  const addLink = useCallback(() => {
    actions.setProp(selectedId, (props: any) => {
      props.links = [...(props.links || []), { text: 'New Link', href: '#' }];
    });
  }, [actions, selectedId]);

  const removeLink = useCallback((index: number) => {
    actions.setProp(selectedId, (props: any) => {
      const updated = [...(props.links || [])];
      updated.splice(index, 1);
      props.links = updated;
    });
  }, [actions, selectedId]);

  /* F2: (re)populate the links array from the current pages list --
     label = page name, href = '/' for the landing page else '/{slug}'.
     Any existing CTA link (isCta: true) is preserved (appended after the
     freshly-generated page links) rather than being wiped, matching the
     legacy GrapesJS builder's "Sync with Pages" behavior. */
  const syncWithPages = useCallback(() => {
    actions.setProp(selectedId, (props: any) => {
      const existing: any[] = props.links || [];
      const ctaLinks = existing.filter((l) => l.isCta);
      const pageLinks = pages.map((p, i) => ({ text: p.name, href: pageHref(p, i) }));
      props.links = [...pageLinks, ...ctaLinks];
    });
  }, [actions, selectedId, pages]);

  /* Detect standalone Logo vs Navbar/Menu */
  const isStandaloneLogo = nodeProps.type !== undefined && (nodeProps.type === 'text' || nodeProps.type === 'image') && nodeProps.logoText === undefined;

  /* Color controls, derived from the props the selected component actually has */
  const colorFields = navColorFields(nodeProps);

  /* Menu layout controls (alignment/orientation/gap/font size). These props are
     unique to the Menu component — Navbar uses navAlignment and has no
     orientation/gap/fontSize — so guarding on their presence scopes this section
     to the Menu without leaking into Navbar or a standalone Logo. */
  const hasMenuLayout = !isStandaloneLogo && (
    nodeProps.alignment !== undefined ||
    nodeProps.orientation !== undefined ||
    nodeProps.gap !== undefined ||
    nodeProps.fontSize !== undefined
  );
  const GAP_PRESETS = ['8px', '16px', '24px', '32px', '40px'].map((g) => ({ label: g, value: g }));

  /* Box-model / animation / visibility values, read off `style` (margin,
     padding, border, boxShadow, opacity) or top-level props (animation,
     hideOn*). This panel is only ever mounted for the 4 owned components
     (Navbar/Menu/Logo/Footer), which all now carry these props (see each
     component's .craft.props), so -- unlike the Links/Colors sections above,
     which are shared across a genuinely disparate prop schema -- these
     sections render unconditionally rather than gating on presence. */
  const style = nodeProps.style || {};

  return (
    <>
      {/* Standalone Logo component settings */}
      {isStandaloneLogo && (
        <CollapsibleSection title="Logo" defaultOpen={true}>
          <div style={sectionGap}>
            <label style={{ ...labelStyle, fontWeight: 600, fontSize: 12, marginBottom: 8 }}>Logo Type</label>
            <div style={{ display: 'flex', gap: 4 }}>
              <button
                onClick={() => setProp('type', 'text')}
                style={{ padding: '4px 10px', fontSize: 11, background: nodeProps.type === 'text' ? '#3b82f6' : '#27272a', color: nodeProps.type === 'text' ? '#fff' : '#a1a1aa', border: `1px solid ${nodeProps.type === 'text' ? '#3b82f6' : '#3f3f46'}`, borderRadius: 4, cursor: 'pointer' }}
              >
                <i className="fa fa-font" style={{ marginRight: 4 }} />Text
              </button>
              <button
                onClick={() => setProp('type', 'image')}
                style={{ padding: '4px 10px', fontSize: 11, background: nodeProps.type === 'image' ? '#3b82f6' : '#27272a', color: nodeProps.type === 'image' ? '#fff' : '#a1a1aa', border: `1px solid ${nodeProps.type === 'image' ? '#3b82f6' : '#3f3f46'}`, borderRadius: 4, cursor: 'pointer' }}
              >
                <i className="fa fa-image" style={{ marginRight: 4 }} />Image
              </button>
            </div>
          </div>
          {nodeProps.type === 'text' && (
            <>
              <div style={sectionGap}>
                <label style={labelStyle}>Logo Text</label>
                <input type="text" value={nodeProps.text || ''} onChange={(e) => setProp('text', e.target.value)} style={inputStyle} />
              </div>
              <div style={sectionGap}>
                <label style={labelStyle}>Font Size</label>
                <input type="text" value={nodeProps.fontSize || '20px'} onChange={(e) => setProp('fontSize', e.target.value)} placeholder="20px" style={inputStyle} />
              </div>
              <div style={sectionGap}>
                <label style={labelStyle}>Font Weight</label>
                <select value={nodeProps.fontWeight || '700'} onChange={(e) => setProp('fontWeight', e.target.value)} style={{ ...inputStyle, cursor: 'pointer' }}>
                  <option value="300">Light</option>
                  <option value="400">Normal</option>
                  <option value="500">Medium</option>
                  <option value="600">Semi</option>
                  <option value="700">Bold</option>
                  <option value="800">Extra Bold</option>
                </select>
              </div>
              <ColorPickerField label="Text Color" value={nodeProps.color || '#1f2937'} onChange={(v) => setProp('color', v)} />
            </>
          )}
          {nodeProps.type === 'image' && (
            <>
              <div style={sectionGap}>
                <label style={labelStyle}>Logo Image</label>
                <AssetPicker value={nodeProps.imageSrc || ''} onChange={(url) => setProp('imageSrc', url)} variant="full" />
              </div>
              <div style={sectionGap}>
                <label style={labelStyle}>Image Width</label>
                <input type="text" value={nodeProps.imageWidth || '120px'} onChange={(e) => setProp('imageWidth', e.target.value)} placeholder="120px" style={inputStyle} />
              </div>
            </>
          )}
          <LinkPicker value={nodeProps.href || '/'} onChange={(v) => setProp('href', v)} />
          <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11, color: '#e4e4e7', cursor: 'pointer', marginTop: -8, marginBottom: 12 }}>
            <input type="checkbox" checked={!!nodeProps.download} onChange={(e) => setProp('download', e.target.checked)} />
            Download (link points at a file)
          </label>
        </CollapsibleSection>
      )}

      {/* Navbar Logo settings */}
      {nodeProps.logoText !== undefined && (
        <CollapsibleSection title="Logo">
          <div style={sectionGap}>
            <label style={labelStyle}>Logo Text</label>
            <input type="text" value={nodeProps.logoText || ''} onChange={(e) => setProp('logoText', e.target.value)} style={inputStyle} />
          </div>
          {nodeProps.logoImage !== undefined && (
            <div style={sectionGap}>
              <label style={labelStyle}>Logo Image</label>
              <AssetPicker value={nodeProps.logoImage || ''} onChange={(url) => setProp('logoImage', url)} variant="full" />
            </div>
          )}
          {nodeProps.logoUrl !== undefined && (
            <LinkPicker value={nodeProps.logoUrl || '/'} onChange={(v) => setProp('logoUrl', v)} />
          )}
        </CollapsibleSection>
      )}

      {/* Links (not shown for standalone Logo, or for components -- like
          Footer -- that don't carry a `links` array at all). */}
      {!isStandaloneLogo && nodeProps.links !== undefined && (
        <CollapsibleSection title="Links">
          <button
            onClick={syncWithPages}
            title="Replace these links with one per page (preserves any CTA link)"
            style={{ marginBottom: 8, width: '100%', padding: '6px', fontSize: 11, background: 'rgba(59,130,246,0.12)', color: '#93c5fd', border: '1px solid rgba(59,130,246,0.4)', borderRadius: 4, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}
          >
            <i className="fa fa-refresh" /> Sync links with Pages
          </button>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {links.map((link, i) => (
              <div key={i} style={{ background: '#1e1e22', borderRadius: 6, padding: 6, display: 'flex', flexDirection: 'column', gap: 3 }}>
                <div style={{ display: 'flex', gap: 4 }}>
                  <input type="text" value={link.text || ''} onChange={(e) => updateLink(i, 'text', e.target.value)} placeholder="Text" style={{ ...smallInputStyle, flex: 1 }} />
                  <button onClick={() => removeLink(i)} style={{ padding: '2px 6px', fontSize: 10, background: '#ef4444', color: '#fff', border: 'none', borderRadius: 4, cursor: 'pointer' }}>
                    <i className="fa fa-times" />
                  </button>
                </div>
                <LinkPicker value={link.href || ''} onChange={(v) => updateLink(i, 'href', v)} />
                <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 10, color: '#a1a1aa', cursor: 'pointer', marginTop: -6 }}>
                  <input type="checkbox" checked={!!link.download} onChange={(e) => updateLink(i, 'download', e.target.checked)} />
                  Download (points at a file)
                </label>
              </div>
            ))}
          </div>
          <button onClick={addLink} style={{ marginTop: 6, width: '100%', padding: '6px', fontSize: 11, background: '#27272a', color: '#e4e4e7', border: '1px solid #3f3f46', borderRadius: 4, cursor: 'pointer' }}>
            + Add Link
          </button>
        </CollapsibleSection>
      )}

      {/* Colors (not shown for standalone Logo - it has its own color picker).
          Fields are derived from whichever color props the selected component
          actually has, so Menu (linkColor/ctaBg/…) and Navbar (backgroundColor/…)
          each get the right controls instead of an empty section. */}
      {!isStandaloneLogo && colorFields.length > 0 && (
        <CollapsibleSection title="Colors">
          {colorFields.map((f) => (
            <ColorPickerField
              key={f.key}
              label={f.label}
              value={nodeProps[f.key] || f.fallback}
              onChange={(v) => setProp(f.key, v)}
            />
          ))}
        </CollapsibleSection>
      )}

      {/* Menu layout (alignment / orientation / gap / font size) */}
      {hasMenuLayout && (
        <CollapsibleSection title="Layout">
          {nodeProps.alignment !== undefined && (
            <div style={sectionGap}>
              <label style={labelStyle}>Alignment</label>
              <div style={{ display: 'flex', gap: 4 }}>
                {(['left', 'center', 'right'] as const).map((a) => (
                  <button key={a} onClick={() => setProp('alignment', a)} style={btnActiveStyle((nodeProps.alignment || 'right') === a)}>
                    {a.charAt(0).toUpperCase() + a.slice(1)}
                  </button>
                ))}
              </div>
            </div>
          )}
          {nodeProps.orientation !== undefined && (
            <div style={sectionGap}>
              <label style={labelStyle}>Orientation</label>
              <div style={{ display: 'flex', gap: 4 }}>
                {(['horizontal', 'vertical'] as const).map((o) => (
                  <button key={o} onClick={() => setProp('orientation', o)} style={btnActiveStyle((nodeProps.orientation || 'horizontal') === o)}>
                    {o.charAt(0).toUpperCase() + o.slice(1)}
                  </button>
                ))}
              </div>
            </div>
          )}
          {nodeProps.gap !== undefined && (
            <div style={sectionGap}>
              <label style={labelStyle}>Gap</label>
              <PresetButtonGrid presets={GAP_PRESETS} activeValue={nodeProps.gap} onSelect={(v) => setProp('gap', v)} />
            </div>
          )}
          {nodeProps.fontSize !== undefined && (
            <div style={sectionGap}>
              <label style={labelStyle}>Font Size</label>
              <input type="text" value={nodeProps.fontSize || '14px'} onChange={(e) => setProp('fontSize', e.target.value)} placeholder="14px" style={inputStyle} />
            </div>
          )}
        </CollapsibleSection>
      )}

      {/* Box model: margin + padding (per-side, via style.*). The old
          single "Padding" preset row is folded into the Padding SpacingControl
          below (still writes to style.padding when linked, matching the
          previous behavior exactly). */}
      <CollapsibleSection title="Spacing" defaultOpen={false}>
        <SpacingControl
          label="Margin"
          value={{ top: style.marginTop, right: style.marginRight, bottom: style.marginBottom, left: style.marginLeft }}
          onChange={(side, v) => setPropStyle(`margin${capitalize(side)}`, v)}
        />
        <SpacingControl
          label="Padding"
          value={{ top: style.paddingTop, right: style.paddingRight, bottom: style.paddingBottom, left: style.paddingLeft }}
          onChange={(side, v) => setPropStyle(`padding${capitalize(side)}`, v)}
          presets={SPACING_PRESETS}
        />
      </CollapsibleSection>

      {/* Border & Effects: border, box-shadow, opacity */}
      <CollapsibleSection title="Border & Effects" defaultOpen={false}>
        <BorderControl
          value={parseBorderShorthand(style.border)}
          onChange={(v) => setPropStyle('border', buildBorderShorthand(v))}
        />
        <div className="guided-section">
          <SectionLabel>Box Shadow</SectionLabel>
          <PresetButtonGrid presets={SHADOW_PRESETS} activeValue={style.boxShadow || 'none'} onSelect={(v) => setPropStyle('boxShadow', v)} />
        </div>
        <div style={sectionGap}>
          <label style={labelStyle}>Opacity</label>
          <input
            type="range"
            min={0}
            max={100}
            value={style.opacity !== undefined ? Math.round(parseFloat(style.opacity) * 100) : 100}
            onChange={(e) => setPropStyle('opacity', String(Number(e.target.value) / 100))}
            style={{ width: '100%' }}
          />
        </div>
      </CollapsibleSection>

      {/* Entrance animation */}
      <CollapsibleSection title="Animation" defaultOpen={false}>
        <AnimationControl
          value={{ animation: nodeProps.animation, animationDelay: nodeProps.animationDelay }}
          onChange={(v) => actions.setProp(selectedId, (p: any) => { p.animation = v.animation; p.animationDelay = v.animationDelay; })}
        />
      </CollapsibleSection>

      {/* Responsive visibility */}
      <CollapsibleSection title="Visibility" defaultOpen={false}>
        <VisibilityControl
          value={{ hideOnDesktop: nodeProps.hideOnDesktop, hideOnTablet: nodeProps.hideOnTablet, hideOnMobile: nodeProps.hideOnMobile }}
          onChange={(v) => actions.setProp(selectedId, (p: any) => { p.hideOnDesktop = v.hideOnDesktop; p.hideOnTablet = v.hideOnTablet; p.hideOnMobile = v.hideOnMobile; })}
        />
      </CollapsibleSection>
    </>
  );
};
