/**
 * Preview component for the live swatch display in the admin settings UI.
 */

import React, { useEffect, useMemo } from "react";
import SwatchGroup from "../../frontend/components/SwatchGroup";
import type { Settings, PreviewMode } from "../types";
import { buildPreviewSelect, getLivePreviewDemoConfig } from "../previewUtils";

export type PreviewProps = {
  rawSettings: Settings;
  showLabels: boolean;
  showLabelsColors: boolean;
  enableTooltips: boolean;
  layoutPaddingTop: number;
  layoutPaddingRight: number;
  layoutPaddingBottom: number;
  layoutPaddingLeft: number;
  labelFontSize: number | string;
  labelTextColor: string;
  mode: PreviewMode;
  selectedColor: string;
  swatchWidth: number;
  swatchHeight: number;
  swatchGap: number;
  selectedIndex: number;
  onSelectIndex: (idx: number) => void;
};

export function Preview(props: PreviewProps): React.ReactElement {
  const {
    rawSettings,
    showLabels,
    showLabelsColors,
    enableTooltips,
    layoutPaddingTop,
    layoutPaddingRight,
    layoutPaddingBottom,
    layoutPaddingLeft,
    labelFontSize,
    labelTextColor,
    mode,
    selectedColor,
    swatchWidth,
    swatchHeight,
    swatchGap,
    selectedIndex,
    onSelectIndex,
  } = props;

  // Live Preview UX: buttons always show text; colors use their dedicated label setting.
  const showLabelsEffective = (() => {
    if (mode === "buttons") return true;
    if (mode === "colors") return showLabelsColors;
    return showLabels; // fallback
  })();

  const demo = useMemo(() => getLivePreviewDemoConfig(), []);

  const values = useMemo(() => {
    if (mode === "colors")
      return demo.colors.map(({ value, label }) => ({ value, label }));
    return demo.buttons.map(({ value, label }) => ({ value, label }));
  }, [demo, mode]);

  const selectEl = useMemo(() => buildPreviewSelect(values), [values]);

  useEffect(() => {
    const clamped = Math.min(Math.max(selectedIndex, 0), values.length - 1);
    const nextValue = values[clamped]?.value;
    if (!nextValue) return;
    if (selectEl.value !== nextValue) {
      selectEl.value = nextValue;
      selectEl.dispatchEvent(new Event("change", { bubbles: true }));
    }
  }, [selectedIndex, selectEl, values]);

  useEffect(() => {
    const onChange = () => {
      const idx = values.findIndex((v) => v.value === selectEl.value);
      if (idx >= 0 && idx !== selectedIndex) onSelectIndex(idx);
    };
    selectEl.addEventListener("change", onChange);
    return () => selectEl.removeEventListener("change", onChange);
  }, [onSelectIndex, selectEl, selectedIndex, values]);

  const items = useMemo(() => {
    const colorsByValue = [...demo.colors, ...demo.buttons].reduce(
      (acc, c) => {
        acc[c.value] = c.color;
        return acc;
      },
      {} as Record<string, string>,
    );

    return { colorsByValue };
  }, [demo]);

  const swatches = useMemo(() => {
    const base = values.reduce(
      (acc, item) => {
        acc[item.value] = {
          label: item.label,
          hide_label: !showLabelsEffective,
        };
        return acc;
      },
      {} as Record<string, { label: string; hide_label: boolean }>,
    );

    if (mode === "colors") {
      return values.reduce((acc, item) => {
        const color = items.colorsByValue[item.value] || "#22c55e";

        acc[item.value] = {
          ...base[item.value],
          type: "color",
          color,
          label: item.label,
        };
        return acc;
      }, {} as any);
    }

    return values.reduce((acc, item) => {
      const color = items.colorsByValue[item.value] || "#22c55e";
      acc[item.value] = {
        ...base[item.value],
        type: "button",
        color,
        label: item.label,
      };
      return acc;
    }, {} as any);
  }, [items, mode, showLabelsEffective, values]);

  const settingsOverride = useMemo(
    () => ({
      // Keep the shared preview payload limited to the base preview shape.
      padding_top: rawSettings.padding_top,
      padding_right: rawSettings.padding_right,
      padding_bottom: rawSettings.padding_bottom,
      padding_left: rawSettings.padding_left,
      external_padding_top: rawSettings.external_padding_top,
      external_padding_right: rawSettings.external_padding_right,
      external_padding_bottom: rawSettings.external_padding_bottom,
      external_padding_left: rawSettings.external_padding_left,
      shape: "square",
      layout: "wrap",
      swatch_style: "underline",
      show_labels: showLabelsEffective,
      show_labels_colors: showLabelsColors,
      enable_tooltips: enableTooltips,
      selected_color: selectedColor,
      swatch_width: swatchWidth,
      swatch_height: swatchHeight,
      label_font_size: labelFontSize,
      label_text_color: labelTextColor,
      layout_padding_top: layoutPaddingTop,
      layout_padding_right: layoutPaddingRight,
      layout_padding_bottom: layoutPaddingBottom,
      layout_padding_left: layoutPaddingLeft,
      swatch_gap: swatchGap,
    }),
    [
      rawSettings,
      enableTooltips,
      labelFontSize,
      labelTextColor,
      layoutPaddingBottom,
      layoutPaddingLeft,
      layoutPaddingRight,
      layoutPaddingTop,
      selectedColor,
      showLabelsEffective,
      showLabelsColors,
      swatchGap,
      swatchHeight,
      swatchWidth,
    ],
  );

  return (
    <SwatchGroup
      attribute="preview"
      select={selectEl}
      swatches={swatches}
      settingsOverride={settingsOverride}
    />
  );
}

export default Preview;
