/**
 * Element Registry System
 *
 * Provides a modular, developer-friendly system for registering
 * custom element types in the Price Builder.
 */

import type { ElementType, PriceScenario } from "../types";
import { createResponsiveValue, createDefaultResponsiveSpacing } from "../types";

// Element definition interface for registry - uses Record for flexible defaultProps
export interface ElementDefinition {
  type: ElementType;
  label: string;
  description: string;
  icon: string; // Icon name from @radix-ui/react-icons
  category: "price" | "badge" | "symbol" | "custom";
  // Which scenarios this element is available in
  availableIn: PriceScenario[];
  // Default properties when creating new element (flexible structure)
  defaultProps: Record<string, unknown>;
  // Validation function (optional)
  validate?: (element: Record<string, unknown>) => boolean;
  // Custom render component name (for custom elements)
  customRenderer?: string;
}

// Registry storage
const elementRegistry = new Map<ElementType, ElementDefinition>();

// Event listeners for registry changes
type RegistryListener = (registry: Map<ElementType, ElementDefinition>) => void;
const listeners: Set<RegistryListener> = new Set();

/**
 * Register a new element type
 */
export function registerElement(definition: ElementDefinition): void {
  if (elementRegistry.has(definition.type)) {
    console.warn(`Element type "${definition.type}" is already registered. Overwriting.`);
  }
  elementRegistry.set(definition.type, definition);
  notifyListeners();
}

/**
 * Unregister an element type
 */
export function unregisterElement(type: ElementType): boolean {
  const result = elementRegistry.delete(type);
  if (result) {
    notifyListeners();
  }
  return result;
}

/**
 * Get element definition by type
 */
export function getElementDefinition(type: ElementType): ElementDefinition | undefined {
  return elementRegistry.get(type);
}

/**
 * Get all registered elements
 */
export function getAllElements(): ElementDefinition[] {
  return Array.from(elementRegistry.values());
}

/**
 * Get elements available for a specific scenario
 */
export function getElementsForScenario(scenario: PriceScenario): ElementDefinition[] {
  return getAllElements().filter((def) => def.availableIn.includes(scenario));
}

/**
 * Get elements by category
 */
export function getElementsByCategory(category: ElementDefinition["category"]): ElementDefinition[] {
  return getAllElements().filter((def) => def.category === category);
}

/**
 * Subscribe to registry changes
 */
export function subscribeToRegistry(listener: RegistryListener): () => void {
  listeners.add(listener);
  return () => {
    listeners.delete(listener);
  };
}

/**
 * Notify all listeners of registry changes
 */
function notifyListeners(): void {
  listeners.forEach((listener) => listener(elementRegistry));
}

/**
 * Check if element type is registered
 */
export function isElementRegistered(type: ElementType): boolean {
  return elementRegistry.has(type);
}

// =====================================================
// Default Element Definitions
// =====================================================

// Default responsive typography
const defaultTypography = {
  fontFamily: "Inter",
  fontSize: createResponsiveValue(24),
  fontWeight: createResponsiveValue(600),
  fontStyle: "normal" as const,
  lineHeight: 1.2,
  letterSpacing: createResponsiveValue(0),
  textTransform: "none" as const,
  textDecoration: "none" as const,
};

const defaultBorder = {
  width: createResponsiveValue(0),
  style: "solid" as const,
  color: "#000000",
  radius: 0,
};

const defaultAnimation = {
  type: "none" as const,
  duration: 300,
  delay: 0,
  easing: "ease-out",
};

// Default responsive padding
const defaultPadding = createDefaultResponsiveSpacing(0);

// Default responsive margin
const defaultMargin = createDefaultResponsiveSpacing(0);

// Base default properties shared by all elements
const baseDefaultProps = {
  rotation: 0,
  zIndex: 1,
  visible: true,
  locked: false,
  backgroundColor: "transparent",
  opacity: 1,
  typography: { ...defaultTypography },
  border: { ...defaultBorder },
  padding: { ...defaultPadding },
  margin: { ...defaultMargin },
  positionType: "relative",
  animation: { ...defaultAnimation },
};

// Regular Price Element
const regularPriceDefinition: ElementDefinition = {
  type: "regularPrice",
  label: "Regular Price",
  description: "Display the regular/original product price",
  icon: "regular",
  category: "price",
  availableIn: ["simple", "sale", "variable_simple", "variable_sale"],
  defaultProps: {
    ...baseDefaultProps,
    name: "Regular Price",
    position: { x: 100, y: 100 },
    // size is calculated by elementFactory based on typography
    color: "#374151",
    decimal: {
      show: true,
      showCurrency: true,
      separator: "point",
      typography: { fontSize: createResponsiveValue(14) },
      position: "superscript",
    },
  },
};

// Sale Price Element
const salePriceDefinition: ElementDefinition = {
  type: "salePrice",
  label: "Sale Price",
  description: "Display the discounted sale price",
  icon: "sale",
  category: "price",
  availableIn: ["sale", "variable_sale"],
  defaultProps: {
    ...baseDefaultProps,
    name: "Sale Price",
    position: { x: 100, y: 150 },
    // size is calculated by elementFactory based on typography
    zIndex: 2,
    color: "#dc2626",
    typography: { ...defaultTypography, fontWeight: createResponsiveValue(700) },
    animation: { ...defaultAnimation, type: "none" },
    decimal: {
      show: true,
      showCurrency: true,
      separator: "point",
      typography: { fontSize: createResponsiveValue(14) },
      position: "superscript",
    },
    lineThrough: {
      enabled: false,
      style: "single",
      color: "#6b7280",
      thickness: 2,
      rotation: 0,
    },
  },
};

// Currency Symbol Element
const currencySymbolDefinition: ElementDefinition = {
  type: "currencySymbol",
  label: "Currency Symbol",
  description: "Display currency symbol ($, €, £, etc.)",
  icon: "currency",
  category: "symbol",
  availableIn: ["simple", "sale", "variable_simple", "variable_sale"],
  defaultProps: {
    ...baseDefaultProps,
    name: "Currency",
    position: { x: 70, y: 100 },
    // size is calculated by elementFactory based on typography
    color: "#374151",
    typography: { ...defaultTypography, fontSize: createResponsiveValue(18) },
    useCustomSvg: false,
    customSvg: null,
    symbolPosition: "before",
  },
};

// Discount Badge Element
const discountBadgeDefinition: ElementDefinition = {
  type: "discountBadge",
  label: "Discount Badge",
  description: "Display discount percentage or amount badge",
  icon: "discount",
  category: "badge",
  availableIn: ["sale", "variable_sale"],
  defaultProps: {
    ...baseDefaultProps,
    name: "Discount",
    position: { x: 200, y: 80 },
    // size is calculated by elementFactory based on typography
    zIndex: 3,
    color: "#ffffff",
    backgroundColor: "#dc2626",
    typography: {
      ...defaultTypography,
      fontSize: createResponsiveValue(14),
      fontWeight: createResponsiveValue(700),
    },
    border: { ...defaultBorder, radius: 4 },
    padding: {
      top: createResponsiveValue(4),
      right: createResponsiveValue(8),
      bottom: createResponsiveValue(4),
      left: createResponsiveValue(8),
    },
    positionType: "relative",
    animation: { ...defaultAnimation, type: "none" },
    format: "percentage",
    customFormat: "-{discount}%",
  },
};

// Text Element
const textElementDefinition: ElementDefinition = {
  type: "text",
  label: "Text",
  description: "Add custom text with full styling options",
  icon: "text",
  category: "custom",
  availableIn: ["simple", "sale", "variable_simple", "variable_sale"],
  defaultProps: {
    ...baseDefaultProps,
    name: "Text",
    position: { x: 100, y: 100 },
    // size is calculated by elementFactory based on typography
    color: "#374151",
    typography: {
      ...defaultTypography,
      fontSize: createResponsiveValue(16),
      fontWeight: createResponsiveValue(400),
    },
    text: "Your text here",
    textAlign: "left",
    verticalAlign: "top",
    widthMode: "auto",
    customWidth: 200,
    backgroundImage: null,
    backgroundImageId: null,
    backgroundSize: "cover",
    backgroundPosition: "center",
    backgroundRepeat: "no-repeat",
  },
};

// Variable Price Range Element
const variablePriceRangeDefinition: ElementDefinition = {
  type: "variablePriceRange",
  label: "Price Range",
  description: "Display variable product price ranges (min-max, From $X, etc.)",
  icon: "range",
  category: "price",
  availableIn: ["variable_simple", "variable_sale"],
  defaultProps: {
    ...baseDefaultProps,
    name: "Price Range",
    position: { x: 100, y: 100 },
    // size is calculated by elementFactory based on typography
    color: "#374151",
    displayMode: "range",
    separator: " – ",
    prefixText: "From",
    showCurrency: true,
    typography: { ...defaultTypography, fontSize: createResponsiveValue(24) },
    // separatorTypography: undefined = inherit proportionally from main typography
    // minPriceTypography: undefined = inherit from main typography
    // maxPriceTypography: undefined = inherit from main typography
    minDecimal: {
      show: true,
      showCurrency: true,
      separator: "point",
      typography: {}, // Empty - inherit proportionally from price font size
      position: "superscript",
    },
    maxDecimal: {
      show: true,
      showCurrency: true,
      separator: "point",
      typography: {}, // Empty - inherit proportionally from price font size
      position: "superscript",
    },
    showOriginalRange: false,
    lineThrough: {
      enabled: false,
      style: "single",
      direction: "horizontal",
      color: "#6b7280",
      thickness: 2,
    },
  },
};

// Register all default elements
export function registerDefaultElements(): void {
  registerElement(regularPriceDefinition);
  registerElement(salePriceDefinition);
  registerElement(currencySymbolDefinition);
  registerElement(discountBadgeDefinition);
  registerElement(textElementDefinition);
  registerElement(variablePriceRangeDefinition);
}

// Initialize default elements on module load
registerDefaultElements();

// Export for external use (developers can extend)
export {
  regularPriceDefinition,
  salePriceDefinition,
  currencySymbolDefinition,
  discountBadgeDefinition,
  textElementDefinition,
  variablePriceRangeDefinition,
};
