/**
 * ContentZone Component
 * Flexible content container with configurable layouts for CMS content assembly
 */

import React, { useState, useCallback, useMemo } from "react";
import {
  ContentZone as ContentZoneType,
  CMSComponent,
  ComponentType,
  LayoutConfig,
  StyleConfig,
  RenderContext,
} from "../types/components.js";

// Mock react-dnd functionality for now
// TODO: Install react-dnd and react-dnd-html5-backend packages
const DndProvider: React.FC<{
  backend: unknown;
  children: React.ReactNode;
}> = ({ children }) => <>{children}</>;
const HTML5Backend = {};

interface DragObject {
  component: CMSComponent;
  index?: number;
}

interface DropCollectedProps {
  isOver: boolean;
}

interface DragCollectedProps {
  isDragging: boolean;
}

const useDrop = (_spec: {
  accept: string;
  drop?: (item: DragObject) => void;
  hover?: (item: DragObject) => void;
  collect: (monitor: unknown) => DropCollectedProps;
}): [DropCollectedProps, (ref: HTMLElement | null) => void] => {
  return [{ isOver: false }, () => {}];
};

const useDrag = (_spec: {
  type: string;
  item: DragObject;
  collect: (monitor: unknown) => DragCollectedProps;
  canDrag?: boolean;
}): [DragCollectedProps, (ref: HTMLElement | null) => void] => {
  return [{ isDragging: false }, () => {}];
};

// ========================================
// Props & Types
// ========================================

export interface ContentZoneProps {
  zone: ContentZoneType;
  context: RenderContext;
  editable?: boolean;
  onComponentAdd?: (component: CMSComponent, index?: number) => void;
  onComponentRemove?: (componentId: string) => void;
  onComponentMove?: (dragIndex: number, hoverIndex: number) => void;
  onComponentUpdate?: (
    componentId: string,
    updates: Partial<CMSComponent>
  ) => void;
  _onZoneUpdate?: (updates: Partial<ContentZoneType>) => void;
  className?: string;
  style?: React.CSSProperties;
}

export interface DraggableComponentProps {
  component: CMSComponent;
  index: number;
  editable: boolean;
  _context: RenderContext;
  onRemove: (id: string) => void;
  _onUpdate: (id: string, updates: Partial<CMSComponent>) => void;
  onMove: (dragIndex: number, hoverIndex: number) => void;
}

export interface DropZoneProps {
  index: number;
  onDrop: (component: CMSComponent, index: number) => void;
  isActive: boolean;
  canDrop: boolean;
}

// ========================================
// Utility Functions
// ========================================

const generateLayoutStyles = (layout: LayoutConfig): React.CSSProperties => {
  const styles: React.CSSProperties = {
    display: layout.display || "block",
    position: layout.position || "relative",
  };

  // Flexbox properties
  if (layout.display === "flex") {
    styles.flexDirection = layout.flexDirection;
    styles.justifyContent = layout.justifyContent;
    styles.alignItems = layout.alignItems;
    styles.flexWrap = layout.flexWrap;
    styles.gap = layout.gap;
  }

  // Grid properties
  if (layout.display === "grid") {
    styles.gridTemplateColumns = layout.gridTemplateColumns;
    styles.gridTemplateRows = layout.gridTemplateRows;
    styles.gridGap = layout.gridGap;
    styles.gridArea = layout.gridArea;
  }

  // Spacing
  if (layout.margin) {
    const margin = layout.margin;
    styles.margin = margin.all;
    if (margin.top) styles.marginTop = margin.top;
    if (margin.right) styles.marginRight = margin.right;
    if (margin.bottom) styles.marginBottom = margin.bottom;
    if (margin.left) styles.marginLeft = margin.left;
    if (margin.x) {
      styles.marginLeft = margin.x;
      styles.marginRight = margin.x;
    }
    if (margin.y) {
      styles.marginTop = margin.y;
      styles.marginBottom = margin.y;
    }
  }

  if (layout.padding) {
    const padding = layout.padding;
    styles.padding = padding.all;
    if (padding.top) styles.paddingTop = padding.top;
    if (padding.right) styles.paddingRight = padding.right;
    if (padding.bottom) styles.paddingBottom = padding.bottom;
    if (padding.left) styles.paddingLeft = padding.left;
    if (padding.x) {
      styles.paddingLeft = padding.x;
      styles.paddingRight = padding.x;
    }
    if (padding.y) {
      styles.paddingTop = padding.y;
      styles.paddingBottom = padding.y;
    }
  }

  // Sizing
  if (layout.width) styles.width = layout.width;
  if (layout.height) styles.height = layout.height;
  if (layout.minWidth) styles.minWidth = layout.minWidth;
  if (layout.maxWidth) styles.maxWidth = layout.maxWidth;
  if (layout.minHeight) styles.minHeight = layout.minHeight;
  if (layout.maxHeight) styles.maxHeight = layout.maxHeight;

  return styles;
};

const generateStyleConfig = (style: StyleConfig): React.CSSProperties => {
  const styles: React.CSSProperties = {};

  // Colors
  if (style.backgroundColor) styles.backgroundColor = style.backgroundColor;
  if (style.color) styles.color = style.color;
  if (style.borderColor) styles.borderColor = style.borderColor;

  // Typography
  if (style.fontSize) styles.fontSize = style.fontSize;
  if (style.fontWeight) styles.fontWeight = style.fontWeight;
  if (style.fontFamily) styles.fontFamily = style.fontFamily;
  if (style.lineHeight) styles.lineHeight = style.lineHeight;
  if (style.textAlign) styles.textAlign = style.textAlign;
  if (style.textDecoration) styles.textDecoration = style.textDecoration;
  if (style.textTransform) styles.textTransform = style.textTransform;

  // Border
  if (style.border) styles.border = style.border;
  if (style.borderWidth) styles.borderWidth = style.borderWidth;
  if (style.borderStyle) styles.borderStyle = style.borderStyle;
  if (style.borderRadius) styles.borderRadius = style.borderRadius;

  // Shadow
  if (style.boxShadow) styles.boxShadow = style.boxShadow;
  if (style.textShadow) styles.textShadow = style.textShadow;

  // Background
  if (style.backgroundImage) styles.backgroundImage = style.backgroundImage;
  if (style.backgroundSize) styles.backgroundSize = style.backgroundSize;
  if (style.backgroundPosition)
    styles.backgroundPosition = style.backgroundPosition;
  if (style.backgroundRepeat) styles.backgroundRepeat = style.backgroundRepeat;

  // Effects
  if (style.opacity !== undefined) styles.opacity = style.opacity;
  if (style.transform) styles.transform = style.transform;
  if (style.transition) styles.transition = style.transition;

  return styles;
};

// ========================================
// Drop Zone Component
// ========================================

const DropZone: React.FC<DropZoneProps> = ({
  index,
  onDrop,
  isActive,
  canDrop,
}) => {
  const [{ isOver }, drop] = useDrop({
    accept: "component",
    drop: (item: DragObject) => onDrop(item.component, index),
    collect: (_monitor: unknown): DropCollectedProps => ({
      isOver: false, // Mock implementation
    }),
  });

  const dropZoneStyles: React.CSSProperties = {
    minHeight: "40px",
    border: "2px dashed #e2e8f0",
    borderColor:
      isOver && canDrop ? "#3b82f6" : isActive ? "#10b981" : "#e2e8f0",
    backgroundColor:
      isOver && canDrop ? "#dbeafe" : isActive ? "#ecfdf5" : "transparent",
    borderRadius: "8px",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    margin: "8px 0",
    transition: "all 0.2s ease",
    opacity: isActive ? 1 : 0.7,
  };

  return (
    <div ref={drop} style={dropZoneStyles}>
      {isActive && (
        <span style={{ color: "#6b7280", fontSize: "14px" }}>
          {isOver && canDrop ? "Drop component here" : "Drop zone"}
        </span>
      )}
    </div>
  );
};

// ========================================
// Draggable Component Wrapper
// ========================================

const DraggableComponent: React.FC<DraggableComponentProps> = ({
  component,
  index,
  editable,
  _context,
  onRemove,
  _onUpdate,
  onMove,
}) => {
  const [isEditing, setIsEditing] = useState(false);

  const [{ isDragging }, drag] = useDrag({
    type: "component",
    item: { component, index },
    collect: (_monitor: unknown): DragCollectedProps => ({
      isDragging: false, // Mock implementation
    }),
    canDrag: editable,
  });

  const [, drop] = useDrop({
    accept: "component",
    hover: (item: DragObject) => {
      if (item.index !== undefined && item.index !== index) {
        onMove(item.index, index);
        item.index = index;
      }
    },
    collect: (_monitor: unknown): DropCollectedProps => ({
      isOver: false,
    }),
  });

  const handleEdit = useCallback(() => {
    setIsEditing(true);
  }, []);

  const handleRemove = useCallback(() => {
    onRemove(component.id);
  }, [component.id, onRemove]);

  const componentStyles = useMemo(() => {
    const layoutStyles = generateLayoutStyles(component.layout);
    const styleConfigStyles = generateStyleConfig(component.style);

    return {
      ...layoutStyles,
      ...styleConfigStyles,
      opacity: isDragging ? 0.5 : 1,
      position: "relative" as const,
      border: editable && isEditing ? "2px solid #3b82f6" : undefined,
      borderRadius: editable && isEditing ? "4px" : undefined,
    };
  }, [component.layout, component.style, isDragging, editable, isEditing]);

  const Component = useMemo(() => {
    // This would be replaced with actual component rendering logic
    // For now, return a placeholder
    return (
      <div style={componentStyles}>
        <div style={{ padding: "16px" }}>
          <h3
            style={{
              margin: "0 0 8px 0",
              fontSize: "16px",
              fontWeight: "bold",
            }}
          >
            {component.name}
          </h3>
          <p style={{ margin: "0", color: "#6b7280", fontSize: "14px" }}>
            {component.description}
          </p>
          <div style={{ marginTop: "8px", fontSize: "12px", color: "#9ca3af" }}>
            Type: {component.type} | Category: {component.category}
          </div>
        </div>
      </div>
    );
  }, [component, componentStyles]);

  return (
    <div
      ref={(node: HTMLElement | null) => {
        drag(node);
        drop(node);
      }}
      style={{ position: "relative" }}
    >
      {Component}

      {editable && (
        <div
          style={{
            position: "absolute",
            top: "8px",
            right: "8px",
            display: "flex",
            gap: "4px",
            opacity: 0.8,
          }}
        >
          <button
            onClick={handleEdit}
            style={{
              background: "#3b82f6",
              color: "white",
              border: "none",
              borderRadius: "4px",
              padding: "4px 8px",
              fontSize: "12px",
              cursor: "pointer",
            }}
          >
            Edit
          </button>
          <button
            onClick={handleRemove}
            style={{
              background: "#ef4444",
              color: "white",
              border: "none",
              borderRadius: "4px",
              padding: "4px 8px",
              fontSize: "12px",
              cursor: "pointer",
            }}
          >
            Remove
          </button>
        </div>
      )}
    </div>
  );
};

// ========================================
// Main ContentZone Component
// ========================================

export const ContentZone: React.FC<ContentZoneProps> = ({
  zone,
  context,
  editable = false,
  onComponentAdd,
  onComponentRemove,
  onComponentMove,
  onComponentUpdate,
  _onZoneUpdate,
  className = "",
  style = {},
}) => {
  const [dragEnabled, setDragEnabled] = useState(editable);

  const handleComponentAdd = useCallback(
    (component: CMSComponent, index?: number) => {
      if (onComponentAdd) {
        onComponentAdd(component, index);
      }
    },
    [onComponentAdd]
  );

  const handleComponentRemove = useCallback(
    (componentId: string) => {
      if (onComponentRemove) {
        onComponentRemove(componentId);
      }
    },
    [onComponentRemove]
  );

  const handleComponentMove = useCallback(
    (dragIndex: number, hoverIndex: number) => {
      if (onComponentMove) {
        onComponentMove(dragIndex, hoverIndex);
      }
    },
    [onComponentMove]
  );

  const handleComponentUpdate = useCallback(
    (componentId: string, updates: Partial<CMSComponent>) => {
      if (onComponentUpdate) {
        onComponentUpdate(componentId, updates);
      }
    },
    [onComponentUpdate]
  );

  const zoneLayoutStyles = useMemo(() => {
    const baseStyles: React.CSSProperties = {
      minHeight: "100px",
      backgroundColor: "#f9fafb",
      borderRadius: "8px",
      padding: "16px",
      ...style,
    };

    // Apply zone-specific layout
    if (zone.layout.gridTemplate) {
      baseStyles.display = "grid";
      baseStyles.gridTemplate = zone.layout.gridTemplate;
    } else {
      baseStyles.display = "grid";
      baseStyles.gridTemplateColumns = `repeat(${zone.layout.columns}, 1fr)`;
      baseStyles.gridTemplateRows = `repeat(${zone.layout.rows}, auto)`;
      baseStyles.gap = "16px";
    }

    return baseStyles;
  }, [zone.layout, style]);

  const canAcceptComponent = useCallback(
    (componentType: ComponentType): boolean => {
      const { constraints } = zone;

      // Check allowed types
      if (
        constraints.allowedTypes &&
        !constraints.allowedTypes.includes(componentType)
      ) {
        return false;
      }

      // Check forbidden types
      if (
        constraints.forbiddenTypes &&
        constraints.forbiddenTypes.includes(componentType)
      ) {
        return false;
      }

      // Check max components
      if (
        constraints.maxComponents &&
        zone.components.length >= constraints.maxComponents
      ) {
        return false;
      }

      return true;
    },
    [zone]
  );

  const renderComponents = useMemo(() => {
    return zone.components.map((component, index) => (
      <React.Fragment key={component.id}>
        {editable && dragEnabled && (
          <DropZone
            index={index}
            onDrop={handleComponentAdd}
            isActive={editable}
            canDrop={canAcceptComponent(component.type)}
          />
        )}
        <DraggableComponent
          component={component}
          index={index}
          editable={editable}
          _context={context}
          onRemove={handleComponentRemove}
          _onUpdate={handleComponentUpdate}
          onMove={handleComponentMove}
        />
      </React.Fragment>
    ));
  }, [
    zone.components,
    editable,
    dragEnabled,
    context,
    handleComponentAdd,
    handleComponentRemove,
    handleComponentUpdate,
    handleComponentMove,
    canAcceptComponent,
  ]);

  return (
    <DndProvider backend={HTML5Backend}>
      <div
        className={`cms-content-zone ${className}`}
        style={zoneLayoutStyles}
        data-zone-id={zone.id}
        data-zone-type={zone.type}
      >
        {/* Zone Header */}
        {editable && (
          <div
            style={{
              display: "flex",
              justifyContent: "space-between",
              alignItems: "center",
              marginBottom: "16px",
              padding: "8px 12px",
              backgroundColor: "#e5e7eb",
              borderRadius: "6px",
              fontSize: "14px",
              fontWeight: "bold",
              color: "#374151",
            }}
          >
            <span>{zone.metadata.title}</span>
            <div style={{ display: "flex", gap: "8px" }}>
              <button
                onClick={() => setDragEnabled(!dragEnabled)}
                style={{
                  background: dragEnabled ? "#10b981" : "#6b7280",
                  color: "white",
                  border: "none",
                  borderRadius: "4px",
                  padding: "4px 8px",
                  fontSize: "12px",
                  cursor: "pointer",
                }}
              >
                {dragEnabled ? "Drag ON" : "Drag OFF"}
              </button>
              <span style={{ fontSize: "12px", color: "#6b7280" }}>
                {zone.components.length}/{zone.layout.maxComponents || "∞"}{" "}
                components
              </span>
            </div>
          </div>
        )}

        {/* Zone Content */}
        <div style={{ position: "relative" }}>
          {renderComponents}

          {/* Final drop zone */}
          {editable && dragEnabled && (
            <DropZone
              index={zone.components.length}
              onDrop={handleComponentAdd}
              isActive={editable}
              canDrop={true}
            />
          )}

          {/* Empty state */}
          {zone.components.length === 0 && (
            <div
              style={{
                display: "flex",
                flexDirection: "column",
                alignItems: "center",
                justifyContent: "center",
                minHeight: "120px",
                color: "#9ca3af",
                textAlign: "center",
              }}
            >
              <div style={{ fontSize: "18px", marginBottom: "8px" }}>📦</div>
              <div style={{ fontSize: "14px", fontWeight: "bold" }}>
                {zone.metadata.title}
              </div>
              <div style={{ fontSize: "12px" }}>
                {zone.metadata.description}
              </div>
              {editable && (
                <div style={{ fontSize: "12px", marginTop: "8px" }}>
                  Drag components here to get started
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </DndProvider>
  );
};

// ========================================
// Export Default
// ========================================

export default ContentZone;
