import React, { CSSProperties, useState } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { useSiteDesign } from '../../state/SiteDesignContext';
import { escapeHtml, escapeAttr, safeUrl, safeImageUrl, cssValue, scopeId } from '../../utils/escape';

/* ---------- Types ---------- */

interface NavLink {
  text: string;
  href: string;
  isExternal?: boolean;
  isCta?: boolean;
  /** Adds the `download` attribute to the exported anchor (F3: links to files). */
  download?: boolean;
}

interface NavbarProps {
  logoType?: 'text' | 'image';
  logoText?: string;
  logoImage?: string;
  logoWidth?: string;
  logoUrl?: string;
  logoFontFamily?: string;
  logoFontSize?: string;
  logoColor?: string;
  links?: NavLink[];
  backgroundColor?: string;
  textColor?: string;
  hoverColor?: string;
  ctaColor?: string;
  ctaTextColor?: string;
  padding?: string;
  navAlignment?: 'left' | 'center' | 'right' | 'space-between';
  isSticky?: boolean;
  showMobileMenu?: boolean;
  style?: CSSProperties;
  hideOnDesktop?: boolean;
  hideOnTablet?: boolean;
  hideOnMobile?: boolean;
  animation?: string;
  animationDelay?: string;
}

/* ---------- Defaults ---------- */

const defaultLinks: NavLink[] = [
  { text: 'Home', href: '/' },
  { text: 'About', href: '#about' },
  { text: 'Services', href: '#services' },
  { text: 'Contact', href: '#contact', isCta: true },
];

const PADDING_PRESETS = [
  { label: 'Compact', value: '8px 16px' },
  { label: 'Normal', value: '16px 24px' },
  { label: 'Relaxed', value: '20px 32px' },
  { label: 'Spacious', value: '24px 48px' },
];

/* ---------- Component ---------- */

export const Navbar: UserComponent<NavbarProps> = ({
  logoType = 'text',
  logoText = 'MySite',
  logoImage = '',
  logoWidth = '120px',
  logoUrl = '/',
  logoFontFamily = 'Inter, sans-serif',
  logoFontSize = '20px',
  logoColor,
  links = defaultLinks,
  backgroundColor = '#ffffff',
  textColor = '#3f3f46',
  hoverColor = '#3b82f6',
  ctaColor = '#3b82f6',
  ctaTextColor = '#ffffff',
  padding = '16px 24px',
  navAlignment = 'space-between',
  isSticky = false,
  showMobileMenu = false,
  style = {},
}) => {
  const {
    connectors: { connect, drag },
    selected,
  } = useNode((node) => ({
    selected: node.events.selected,
  }));

  const { design } = useSiteDesign();
  const resolvedLogoColor = logoColor || (backgroundColor === '#ffffff' || backgroundColor === '#f8fafc' || backgroundColor === '#f9fafb' ? design.textColor : '#ffffff');
  const resolvedTextColor = textColor || (backgroundColor === '#ffffff' || backgroundColor === '#f8fafc' || backgroundColor === '#f9fafb' ? '#3f3f46' : '#e4e4e7');

  const [hoveredLink, setHoveredLink] = useState<number | null>(null);

  return (
    <nav
      ref={(ref: HTMLElement | null): void => { if (ref) connect(drag(ref)); }}
      style={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: navAlignment,
        padding,
        backgroundColor,
        ...(isSticky ? { position: 'sticky' as const, top: 0, zIndex: 1000 } : {}),
        outline: selected ? '2px solid #3b82f6' : 'none',
        ...style,
      }}
    >
      {/* Logo */}
      <a
        href={logoUrl}
        onClick={(e) => e.preventDefault()}
        style={{ textDecoration: 'none', display: 'flex', alignItems: 'center', flexShrink: 0 }}
      >
        {logoType === 'image' && logoImage ? (
          <img
            src={logoImage}
            alt={logoText || 'Logo'}
            style={{ width: logoWidth, height: 'auto', display: 'block' }}
          />
        ) : (
          <span style={{
            fontWeight: '700',
            fontSize: logoFontSize,
            fontFamily: logoFontFamily,
            color: resolvedLogoColor,
          }}>
            {logoText}
          </span>
        )}
      </a>

      {/* Links */}
      <div style={{ display: 'flex', alignItems: 'center', gap: '24px' }}>
        {showMobileMenu && (
          <div
            style={{
              display: 'none', /* Hidden in editor, shown via media query in export */
              flexDirection: 'column',
              gap: '4px',
              cursor: 'pointer',
              padding: '4px',
            }}
            className="navbar-hamburger"
          >
            <span style={{ display: 'block', width: '24px', height: '2px', backgroundColor: resolvedTextColor }} />
            <span style={{ display: 'block', width: '24px', height: '2px', backgroundColor: resolvedTextColor }} />
            <span style={{ display: 'block', width: '24px', height: '2px', backgroundColor: resolvedTextColor }} />
          </div>
        )}
        {links.map((link, i) => (
          <a
            key={i}
            href={link.href}
            target={link.isExternal ? '_blank' : undefined}
            rel={link.isExternal ? 'noopener noreferrer' : undefined}
            download={link.download || undefined}
            onClick={(e) => e.preventDefault()}
            onMouseEnter={() => setHoveredLink(i)}
            onMouseLeave={() => setHoveredLink(null)}
            style={{
              textDecoration: 'none',
              fontSize: '14px',
              fontWeight: link.isCta ? '600' : '400',
              color: link.isCta
                ? ctaTextColor
                : (hoveredLink === i ? hoverColor : resolvedTextColor),
              backgroundColor: link.isCta ? ctaColor : 'transparent',
              padding: link.isCta ? '8px 20px' : '0',
              borderRadius: link.isCta ? '6px' : '0',
              transition: 'color 0.15s, background-color 0.15s',
              ...(link.isCta && hoveredLink === i ? { filter: 'brightness(1.1)' } : {}),
            }}
          >
            {link.text}
          </a>
        ))}
      </div>
    </nav>
  );
};

/* ---------- Craft config ---------- */

Navbar.craft = {
  displayName: 'Navbar',
  props: {
    logoType: 'text',
    logoText: 'MySite',
    logoImage: '',
    logoWidth: '120px',
    logoUrl: '/',
    logoFontFamily: 'Inter, sans-serif',
    logoFontSize: '20px',
    logoColor: undefined,
    links: defaultLinks,
    backgroundColor: '#ffffff',
    textColor: '#3f3f46',
    hoverColor: '#3b82f6',
    ctaColor: '#3b82f6',
    ctaTextColor: '#ffffff',
    padding: '16px 24px',
    navAlignment: 'space-between',
    isSticky: false,
    showMobileMenu: false,
    style: {
      borderBottom: '1px solid #e4e4e7',
    },
    hideOnDesktop: false,
    hideOnTablet: false,
    hideOnMobile: false,
    animation: 'none',
    animationDelay: '0',
  } as NavbarProps,
  rules: {
    canDrag: () => true,
    canMoveIn: () => false,
    canMoveOut: () => true,
  },
};

/* ---------- HTML export ---------- */

(Navbar as any).toHtml = (props: NavbarProps, _childrenHtml: string, nodeId?: string) => {
  // Sanitized once here -- these are raw string-interpolation sinks below
  // (hoverCol/bgColor go into a <style> block, the worst case: </style>
  // breakout -> arbitrary <script>), see task-cssxss-brief.md.
  const bgColor = cssValue(props.backgroundColor) || '#ffffff';
  const textCol = cssValue(props.textColor) || '#3f3f46';
  const hoverCol = cssValue(props.hoverColor) || '#3b82f6';
  const ctaCol = cssValue(props.ctaColor) || '#3b82f6';
  const ctaTextCol = cssValue(props.ctaTextColor) || '#ffffff';
  const pad = cssValue(props.padding) || '16px 24px';
  const alignment = props.navAlignment || 'space-between';
  const sticky = props.isSticky;
  const mobile = props.showMobileMenu;
  const logoUrl = props.logoUrl || '/';
  const links0 = props.links || defaultLinks;

  // M-1: deterministic AND unique per-instance scope, keyed on the Craft
  // node id. Two Navbars on the same page previously emitted an identical
  // fixed id="navbar-links" (invalid duplicate-id HTML, ambiguous
  // aria-controls target) and unscoped `.navbar-link:hover`/`.navbar-cta:hover`
  // rules in each instance's own <style> block -- since both blocks target
  // the SAME global selector, the later one in the DOM silently overrides
  // the earlier one's hover color/behavior for BOTH navbars. Scoping the
  // links-container id and adding a per-instance class on the <nav> root
  // (used to prefix the hover selectors) eliminates both collisions.
  const scope = scopeId(nodeId, JSON.stringify(links0) + alignment + pad, 'nav');
  const linksId = `${scope}_links`;

  const navStyle = cssPropsToString({
    display: 'flex',
    alignItems: 'center',
    justifyContent: alignment,
    padding: pad,
    backgroundColor: bgColor,
    ...(sticky ? { position: 'sticky', top: '0', zIndex: '1000' } : {}),
    ...props.style,
  });

  // Logo HTML
  let logoHtml: string;
  if (props.logoType === 'image' && props.logoImage) {
    const imgStyle = cssPropsToString({ width: props.logoWidth || '120px', height: 'auto', display: 'block' });
    logoHtml = `<a href="${escapeAttr(safeUrl(logoUrl))}" style="text-decoration:none;display:flex;align-items:center;flex-shrink:0"><img src="${escapeAttr(safeImageUrl(props.logoImage))}" alt="${escapeAttr(props.logoText || 'Logo')}"${imgStyle ? ` style="${imgStyle}"` : ''} /></a>`;
  } else {
    const logoStyle = cssPropsToString({
      fontWeight: '700',
      fontSize: props.logoFontSize || '20px',
      fontFamily: props.logoFontFamily || 'Inter, sans-serif',
      color: props.logoColor || textCol,
    });
    logoHtml = `<a href="${escapeAttr(safeUrl(logoUrl))}" style="text-decoration:none;display:flex;align-items:center;flex-shrink:0"><span${logoStyle ? ` style="${logoStyle}"` : ''}>${escapeHtml(props.logoText || 'MySite')}</span></a>`;
  }

  // Links HTML
  const links = props.links || defaultLinks;
  const linksHtml = links.map((link) => {
    const target = link.isExternal ? ' target="_blank" rel="noopener noreferrer"' : '';
    const linkStyle = cssPropsToString({
      textDecoration: 'none',
      fontSize: '14px',
      fontWeight: link.isCta ? '600' : '400',
      color: link.isCta ? ctaTextCol : textCol,
      backgroundColor: link.isCta ? ctaCol : 'transparent',
      padding: link.isCta ? '8px 20px' : '0',
      borderRadius: link.isCta ? '6px' : '0',
      transition: 'color 0.15s, background-color 0.15s',
    });
    return `<a href="${escapeAttr(safeUrl(link.href || "#"))}"${target}${linkStyle ? ` style="${linkStyle}"` : ''}>${escapeHtml(link.text)}</a>`;
  }).join('\n      ');

  // Hamburger HTML for mobile. The toggle needs an accessible name (there's
  // no visible text, just three bars) and must report its open/closed state
  // via aria-expanded, kept in sync with the .navbar-open class by the
  // inline onclick handler.
  const hamburgerHtml = mobile
    ? `\n    <button class="navbar-hamburger" aria-label="Toggle navigation menu" aria-expanded="false" aria-controls="${escapeAttr(linksId)}" onclick="var m=document.getElementById('${linksId}');var open=m.classList.toggle('navbar-open');this.setAttribute('aria-expanded', open ? 'true' : 'false');" style="display:none;background:none;border:none;cursor:pointer;padding:4px;flex-direction:column;gap:4px">
      <span style="display:block;width:24px;height:2px;background-color:${escapeAttr(textCol)}"></span>
      <span style="display:block;width:24px;height:2px;background-color:${escapeAttr(textCol)}"></span>
      <span style="display:block;width:24px;height:2px;background-color:${escapeAttr(textCol)}"></span>
    </button>`
    : '';

  // Hover CSS -- scoped under `.${scope}` (a class on the <nav> root, added
  // below) so it can only ever match THIS instance's links/CTA, never bleed
  // into or get overridden by another Navbar instance's rules.
  const hoverCss = `<style>
  .${scope} .navbar-link:hover { color: ${hoverCol} !important; }
  .${scope} .navbar-cta:hover { filter: brightness(1.1); }${mobile ? `
  @media (max-width: 768px) {
    .${scope} .navbar-hamburger { display: flex !important; }
    .${scope} .navbar-links { display: none !important; position: absolute; top: 100%; left: 0; right: 0; flex-direction: column !important; background-color: ${bgColor}; padding: 12px 24px; gap: 12px !important; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
    .${scope} .navbar-links.navbar-open { display: flex !important; }
  }` : ''}
</style>`;

  // Add CSS class to each link for hover
  const linksHtmlWithClass = links.map((link) => {
    const target = link.isExternal ? ' target="_blank" rel="noopener noreferrer"' : '';
    const downloadAttr = link.download ? ' download' : '';
    const cls = link.isCta ? 'navbar-cta' : 'navbar-link';
    const linkStyle = cssPropsToString({
      textDecoration: 'none',
      fontSize: '14px',
      fontWeight: link.isCta ? '600' : '400',
      color: link.isCta ? ctaTextCol : textCol,
      backgroundColor: link.isCta ? ctaCol : 'transparent',
      padding: link.isCta ? '8px 20px' : '0',
      borderRadius: link.isCta ? '6px' : '0',
      transition: 'color 0.15s, background-color 0.15s',
    });
    return `<a href="${escapeAttr(safeUrl(link.href || "#"))}" class="${cls}"${target}${downloadAttr}${linkStyle ? ` style="${linkStyle}"` : ''}>${escapeHtml(link.text)}</a>`;
  }).join('\n      ');

  return {
    html: `${hoverCss}
<nav class="${scope}"${navStyle ? ` style="${navStyle}${mobile ? ';position:relative' : ''}"` : ''}>
  ${logoHtml}${hamburgerHtml}
  <div class="navbar-links" id="${linksId}" style="display:flex;align-items:center;gap:24px">
      ${linksHtmlWithClass}
  </div>
</nav>`,
  };
};
