import React, { CSSProperties } from 'react';
import { useNode, Element, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { Container } from './Container';
import { escapeAttr, cssValue } from '../../utils/escape';

/* ---------- Shape Divider SVG Paths ---------- */

type DividerShape = 'none' | 'wave' | 'angle' | 'curve' | 'triangle' | 'zigzag';

const DIVIDER_PATHS: Record<Exclude<DividerShape, 'none'>, string> = {
  wave: 'M0,0 C150,120 350,0 600,60 C850,120 1050,0 1200,60 L1200,120 L0,120 Z',
  angle: 'M0,0 L1200,120 L0,120 Z',
  curve: 'M0,0 Q600,140 1200,0 L1200,120 L0,120 Z',
  triangle: 'M0,120 L600,0 L1200,120 Z',
  zigzag: 'M0,120 L100,40 L200,120 L300,40 L400,120 L500,40 L600,120 L700,40 L800,120 L900,40 L1000,120 L1100,40 L1200,120 Z',
};

interface SectionProps {
  style?: CSSProperties;
  innerMaxWidth?: string;
  children?: React.ReactNode;
  topDivider?: DividerShape;
  topDividerColor?: string;
  topDividerHeight?: string;
  bottomDivider?: DividerShape;
  bottomDividerColor?: string;
  bottomDividerHeight?: string;
  anchorId?: string;
  hideOnDesktop?: boolean;
  hideOnTablet?: boolean;
  hideOnMobile?: boolean;
  animation?: string;
  animationDelay?: string;
}

/* ---------- Divider renderer ---------- */

const ShapeDivider: React.FC<{
  shape: DividerShape;
  color: string;
  height: string;
  position: 'top' | 'bottom';
}> = ({ shape, color, height, position }) => {
  if (!shape || shape === 'none') return null;
  // `shape` is attacker-controlled (AI update_props / deserialized state) and
  // not runtime-type-checked. A plain-object index lookup with a string key
  // like '__proto__', 'toString', or 'constructor' returns an INHERITED
  // Object.prototype value (not undefined), which would otherwise leak
  // "[object Object]" / a function's source text into the SVG `d` attribute
  // below. hasOwnProperty restricts the lookup to the real allowlisted keys.
  if (!Object.prototype.hasOwnProperty.call(DIVIDER_PATHS, shape)) return null;
  const path = DIVIDER_PATHS[shape as Exclude<DividerShape, 'none'>];
  if (!path) return null;

  const isTop = position === 'top';

  return (
    <div
      style={{
        position: 'absolute',
        [position]: 0,
        left: 0,
        right: 0,
        height: height || '50px',
        overflow: 'hidden',
        lineHeight: 0,
        pointerEvents: 'none',
      }}
    >
      <svg
        viewBox="0 0 1200 120"
        preserveAspectRatio="none"
        style={{
          width: '100%',
          height: '100%',
          fill: color || '#ffffff',
          transform: isTop ? 'rotate(180deg)' : undefined,
          display: 'block',
        }}
      >
        <path d={path} />
      </svg>
    </div>
  );
};

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

export const Section: UserComponent<SectionProps> = ({
  style = {},
  innerMaxWidth = '1200px',
  children,
  topDivider = 'none',
  topDividerColor = '#ffffff',
  topDividerHeight = '50px',
  bottomDivider = 'none',
  bottomDividerColor = '#ffffff',
  bottomDividerHeight = '50px',
  anchorId,
}) => {
  const { connectors: { connect, drag } } = useNode();

  const hasTopDivider = topDivider && topDivider !== 'none';
  const hasBottomDivider = bottomDivider && bottomDivider !== 'none';
  // Section's root only becomes a column flex container when the user has
  // actually set `style.justifyContent` (Vertical Alignment control, paired
  // with `style.minHeight`) -- see the matching note in Container.tsx for
  // why an unconditional conversion is a real regression (blockifies
  // deliberately inline-block children like ButtonLink/Icon) rather than a
  // no-op, so plain block flow is preserved unless vertical-align is set.
  const hasVerticalAlign = !!style.justifyContent;

  return (
    <section
      ref={(ref: HTMLElement | null) => { if (ref) connect(drag(ref)); }}
      id={anchorId || undefined}
      style={{
        width: '100%',
        position: (hasTopDivider || hasBottomDivider) ? 'relative' : undefined,
        ...style,
        ...(hasVerticalAlign ? { display: 'flex', flexDirection: 'column' } : {}),
      }}
    >
      {hasTopDivider && (
        <ShapeDivider
          shape={topDivider}
          color={topDividerColor}
          height={topDividerHeight}
          position="top"
        />
      )}
      <Element
        id="section-inner"
        is={Container}
        canvas
        style={{ maxWidth: innerMaxWidth, margin: '0 auto', position: 'relative', zIndex: 1 }}
        tag="div"
      >
        {children}
      </Element>
      {hasBottomDivider && (
        <ShapeDivider
          shape={bottomDivider}
          color={bottomDividerColor}
          height={bottomDividerHeight}
          position="bottom"
        />
      )}
    </section>
  );
};

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

Section.craft = {
  displayName: 'Section',
  props: {
    style: {
      padding: '40px 0',
      backgroundColor: '#ffffff',
      minHeight: '',
      justifyContent: '',
      marginTop: '', marginRight: '', marginBottom: '', marginLeft: '',
      paddingTop: '', paddingRight: '', paddingBottom: '', paddingLeft: '',
      border: 'none',
      boxShadow: 'none',
      opacity: '1',
    },
    innerMaxWidth: '1200px',
    topDivider: 'none',
    topDividerColor: '#ffffff',
    topDividerHeight: '50px',
    bottomDivider: 'none',
    bottomDividerColor: '#ffffff',
    bottomDividerHeight: '50px',
    anchorId: '',
    animation: '',
    animationDelay: '0',
    hideOnDesktop: false,
    hideOnTablet: false,
    hideOnMobile: false,
  },
  rules: {
    canDrag: () => true,
    canMoveIn: () => true,
    canMoveOut: () => true,
  },
};

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

function buildDividerHtml(
  shape: DividerShape | undefined,
  color: string | undefined,
  height: string | undefined,
  position: 'top' | 'bottom',
): string {
  if (!shape || shape === 'none') return '';
  // See the matching hasOwnProperty guard in <ShapeDivider> above -- same
  // prototype-pollution-shaped lookup, same fix.
  if (!Object.prototype.hasOwnProperty.call(DIVIDER_PATHS, shape)) return '';
  const path = DIVIDER_PATHS[shape as Exclude<DividerShape, 'none'>];
  if (!path) return '';

  const isTop = position === 'top';
  const h = height || '50px';
  // Sanitized -- raw string-interpolation sink in the SVG `fill:${c}` below.
  const c = cssValue(color) || '#ffffff';

  const wrapperStyle = cssPropsToString({
    position: 'absolute',
    [position]: '0',
    left: '0',
    right: '0',
    height: h,
    overflow: 'hidden',
    lineHeight: '0',
    pointerEvents: 'none',
  } as CSSProperties);

  const svgTransform = isTop ? ' transform:rotate(180deg);' : '';

  return `<div style="${wrapperStyle}"><svg viewBox="0 0 1200 120" preserveAspectRatio="none" style="width:100%;height:100%;fill:${c};display:block;${svgTransform}"><path d="${path}"/></svg></div>`;
}

(Section as any).toHtml = (props: SectionProps, childrenHtml: string) => {
  const hasTopDivider = props.topDivider && props.topDivider !== 'none';
  const hasBottomDivider = props.bottomDivider && props.bottomDivider !== 'none';
  const hasVerticalAlign = !!props.style?.justifyContent;

  const outerStyle = cssPropsToString({
    width: '100%',
    position: (hasTopDivider || hasBottomDivider) ? 'relative' : undefined,
    ...props.style,
    ...(hasVerticalAlign ? { display: 'flex', flexDirection: 'column' } : {}),
  });
  const innerStyle = cssPropsToString({
    maxWidth: props.innerMaxWidth || '1200px',
    margin: '0 auto',
    position: (hasTopDivider || hasBottomDivider) ? 'relative' : undefined,
    zIndex: (hasTopDivider || hasBottomDivider) ? 1 : undefined,
  } as CSSProperties);

  const topHtml = buildDividerHtml(props.topDivider, props.topDividerColor, props.topDividerHeight, 'top');
  const bottomHtml = buildDividerHtml(props.bottomDivider, props.bottomDividerColor, props.bottomDividerHeight, 'bottom');
  const idAttr = props.anchorId ? ` id="${escapeAttr(props.anchorId)}"` : '';

  return {
    html: `<section${idAttr}${outerStyle ? ` style="${outerStyle}"` : ''}>${topHtml}<div${innerStyle ? ` style="${innerStyle}"` : ''}>${childrenHtml}</div>${bottomHtml}</section>`,
  };
};
