/**
 * Price Builder Types
 */

// Price scenario types
export type PriceScenario = "simple" | "sale" | "variable_simple" | "variable_sale";

// Layout location type (dynamic from API)
export type LayoutLocation = string;

// Location definition from API/PHP
export interface LocationDefinition {
  key: string;
  label: string;
  description: string;
}

/**
 * Get available locations from the PHP-provided config.
 * Falls back to defaults if not available.
 */
export function getAvailableLocations(): LocationDefinition[] {
  if (typeof window !== "undefined" && window.oppbAdmin?.locations) {
    return window.oppbAdmin.locations;
  }

  // Fallback defaults (should match PHP Locations class defaults)
  return [
    {
      key: "single_product",
      label: "Single Product",
      description: "Main product page price display",
    },
    {
      key: "loop",
      label: "Loop",
      description: "Shop, category, archive pages and related products",
    },
  ];
}

/**
 * Get locations as a key-label map (for backward compatibility).
 */
export function getLocationsMap(): Record<string, string> {
  const locations = getAvailableLocations();
  return locations.reduce(
    (acc, loc) => {
      acc[loc.key] = loc.label;
      return acc;
    },
    {} as Record<string, string>,
  );
}

// Element types available in the builder
export type ElementType = "regularPrice" | "salePrice" | "currencySymbol" | "discountBadge" | "text" | "variablePriceRange";

// Position for absolute/relative elements
export interface Position {
  x: number;
  y: number;
}

// Size dimensions
export interface Size {
  width: number;
  height: number;
}

// ==========================================================================
// Responsive System Types
// ==========================================================================

// Breakpoint identifiers
export type Breakpoint = "desktop" | "tablet" | "mobile";

// Responsive value wrapper - holds values for each breakpoint
export interface ResponsiveValue<T> {
  desktop: T;
  tablet: T;
  mobile: T;
}

// Helper type to make a value responsive or static
export type MaybeResponsive<T> = T | ResponsiveValue<T>;

// Check if a value is responsive
export function isResponsiveValue<T>(value: MaybeResponsive<T>): value is ResponsiveValue<T> {
  return typeof value === "object" && value !== null && "desktop" in value && "tablet" in value && "mobile" in value;
}

// Get value for specific breakpoint
export function getBreakpointValue<T>(value: MaybeResponsive<T>, breakpoint: Breakpoint): T {
  if (isResponsiveValue(value)) {
    return value[breakpoint];
  }
  return value;
}

// Create a responsive value with same value for all breakpoints
export function createResponsiveValue<T>(value: T): ResponsiveValue<T> {
  return {
    desktop: value,
    tablet: value,
    mobile: value,
  };
}

// Responsive spacing settings (for padding/margin)
export interface ResponsiveSpacing {
  top: ResponsiveValue<number>;
  right: ResponsiveValue<number>;
  bottom: ResponsiveValue<number>;
  left: ResponsiveValue<number>;
}

// Create default responsive spacing
export function createDefaultResponsiveSpacing(value: number = 0): ResponsiveSpacing {
  return {
    top: createResponsiveValue(value),
    right: createResponsiveValue(value),
    bottom: createResponsiveValue(value),
    left: createResponsiveValue(value),
  };
}

// Responsive typography settings (only some props are responsive)
export interface ResponsiveTypographySettings {
  fontFamily: string;
  fontSize: ResponsiveValue<number>;
  fontWeight: ResponsiveValue<number>;
  fontStyle: "normal" | "italic";
  lineHeight: number;
  letterSpacing: ResponsiveValue<number>;
  textTransform: "none" | "uppercase" | "lowercase" | "capitalize";
  textDecoration: "none" | "underline" | "line-through";
}

// Responsive border settings (only width is responsive)
export interface ResponsiveBorderSettings {
  width: ResponsiveValue<number>;
  style: "solid" | "dashed" | "dotted";
  color: string;
  radius: number;
}

// ==========================================================================
// Standard Settings (non-responsive, for backwards compatibility)
// ==========================================================================

// Typography settings
export interface TypographySettings {
  fontFamily: string;
  fontSize: number;
  fontWeight: number;
  fontStyle: "normal" | "italic";
  lineHeight: number;
  letterSpacing: number;
  textTransform: "none" | "uppercase" | "lowercase" | "capitalize";
  textDecoration: "none" | "underline" | "line-through";
}

// Decimal settings for price elements
export interface DecimalSettings {
  show: boolean;
  showCurrency: boolean;
  separator: "comma" | "point" | "none";
  typography: Partial<ResponsiveTypographySettings>;
  position: "inline" | "top" | "superscript" | "baseline" | "absolute";
  absoluteOffset?: Position;
}

// Line-through settings for price elements
export interface LineThroughSettings {
  enabled: boolean;
  style: "single" | "double" | "cross";
  direction: "horizontal" | "diagonal-down" | "diagonal-up";
  color: string;
  thickness: number;
}

// CountUp animation easing function types
export type CountUpEasing =
  | "easeOutExpo" // Default - fast start, slow end (best for most cases)
  | "easeOutQuart" // Smooth deceleration
  | "easeOutCubic" // Gentle slowdown
  | "easeOutQuad" // Subtle easing
  | "easeInOutQuad" // Smooth both ways
  | "easeInOutExpo" // Dramatic both ways
  | "linear"; // No easing

// CountUp specific settings (Pro feature)
export interface CountUpSettings {
  startVal: number | null; // Starting value (null = auto-calculate from number length, e.g., 891 -> 100)
  decimalPlaces: number; // Number of decimal places (auto-detected if not set)
  useGrouping: boolean; // Use thousand separators (default: true)
  useEasing: boolean; // Enable easing (default: true)
  easingFn: CountUpEasing; // Easing function
  enableScrollSpy: boolean; // Start on scroll into view (default: true)
  scrollSpyOnce: boolean; // Only animate once on scroll (default: true)
  animateDecimals: boolean; // Whether to animate decimal portion (default: true)
  decimalDelay: number; // Additional delay for decimal animation in ms (default: 100)
  step: number; // Increment step for counting (default: 1)
}

// Animation settings
export interface AnimationSettings {
  type: "none" | "fadeIn" | "slideIn" | "scaleIn" | "countUp" | "pulse" | "glow";
  duration: number;
  delay: number;
  easing: string;
  direction?: "left" | "right" | "top" | "bottom";
  // CountUp specific settings (only used when type is "countUp")
  countUp?: CountUpSettings;
}

// Border settings
export interface BorderSettings {
  width: number;
  style: "solid" | "dashed" | "dotted";
  color: string;
  radius: number;
}

// Padding/Margin settings
export interface SpacingSettings {
  top: number;
  right: number;
  bottom: number;
  left: number;
}

// Container settings for oppb-price-container
export interface ContainerSettings {
  // Border (responsive)
  border: ResponsiveBorderSettings;
  // Spacing (responsive)
  padding: ResponsiveSpacing;
  margin: ResponsiveSpacing;
  // Background
  backgroundColor: string;
  backgroundImage: string | null;
  backgroundImageId: number | null;
  backgroundSize: "cover" | "contain" | "auto";
  backgroundPosition: "center" | "top" | "bottom" | "left" | "right";
  backgroundRepeat: "no-repeat" | "repeat" | "repeat-x" | "repeat-y";
}

// Base element interface
export interface BaseElement {
  id: string;
  type: ElementType;
  name: string;
  position: Position;
  size: Size;
  rotation: number;
  zIndex: number;
  visible: boolean;
  locked: boolean;

  // Styling
  color: string;
  backgroundColor: string;
  opacity: number;
  typography: ResponsiveTypographySettings;
  border: ResponsiveBorderSettings;
  padding: ResponsiveSpacing;
  margin: ResponsiveSpacing;

  // Layout
  positionType: "relative" | "absolute";

  // Animation
  animation: AnimationSettings;
}

// Price element (extends base with decimal settings)
export interface PriceElement extends BaseElement {
  type: "regularPrice" | "salePrice";
  decimal: DecimalSettings;
  lineThrough?: LineThroughSettings;
}

// Currency symbol element
export interface CurrencyElement extends BaseElement {
  type: "currencySymbol";
  symbol: string; // The currency symbol to display (e.g., "$", "€", "£")
  symbolCode: string; // ISO currency code (e.g., "USD", "EUR", "GBP")
  useCustomImage: boolean; // Whether to use a custom image instead of symbol
  customImageUrl: string | null; // URL of custom image from media library
  customImageId: number | null; // WordPress attachment ID
  // Legacy properties (kept for backwards compatibility)
  useCustomSvg: boolean;
  customSvg: string | null;
  symbolPosition: "before" | "after";
}

// Discount badge element
export interface DiscountBadgeElement extends BaseElement {
  type: "discountBadge";
  format: "percentage" | "amount" | "custom";
  customFormat: string;
}

// Text element
export interface TextElement extends BaseElement {
  type: "text";
  text: string;
  textAlign: "left" | "center" | "right" | "justify";
  verticalAlign: "top" | "middle" | "bottom";
  widthMode: "auto" | "full" | "custom";
  customWidth: number;
  // Background image (optional)
  backgroundImage: string | null;
  backgroundImageId: number | null;
  backgroundSize: "cover" | "contain" | "auto";
  backgroundPosition: "center" | "top" | "bottom" | "left" | "right";
  backgroundRepeat: "no-repeat" | "repeat" | "repeat-x" | "repeat-y";
}

// Variable Price Range element
export interface VariablePriceRangeElement extends BaseElement {
  type: "variablePriceRange";
  // Display mode
  displayMode: "range" | "from" | "up-to" | "min-only" | "max-only";
  // Separator text (for range mode)
  separator: string;
  // Prefix text (for "from", "up-to" modes)
  prefixText: string;
  // Whether to show currency with each price
  showCurrency: boolean;
  // Typography for separator/prefix text (optional - inherits from main typography if not set)
  separatorTypography?: Partial<ResponsiveTypographySettings>;
  // Typography for min price (optional - inherits from main typography if not set)
  minPriceTypography?: Partial<ResponsiveTypographySettings>;
  // Typography for max price (optional - inherits from main typography if not set)
  maxPriceTypography?: Partial<ResponsiveTypographySettings>;
  // Decimal settings for min price
  minDecimal: DecimalSettings;
  // Decimal settings for max price
  maxDecimal: DecimalSettings;
  // Sale mode: show original range with line-through
  showOriginalRange: boolean;
  // Line-through settings for original prices
  lineThrough?: LineThroughSettings;
}

// Union type for all elements
export type CanvasElement = PriceElement | CurrencyElement | DiscountBadgeElement | TextElement | VariablePriceRangeElement;

// Canvas state
export interface CanvasState {
  elements: CanvasElement[];
  selectedIds: string[];
  hoveredId: string | null;
  containerSelected: boolean;
  containerSettings: ContainerSettings;
  zoom: number;
  pan: Position;
  showGrid: boolean;
  showGuides: boolean;
  showContainerBounds: boolean;
  snapToGuides: boolean;
  snapThreshold: number;
  activeGuides: SnapGuide[];
  presetId?: string | null;
}

// Snap guide
export interface SnapGuide {
  type: "vertical" | "horizontal";
  position: number;
  start: number;
  end: number;
}

// Layout template
export interface LayoutTemplate {
  id: number;
  name: string;
  slug: string;
  scenario: PriceScenario;
  // Location-based activation (flexible, dynamic locations)
  activeLocations: Record<string, boolean>;
  canvasData: CanvasState;
  settingsData: Record<string, unknown>;
  exportedHtml: string;
  exportedCss: string;
  exportedJs: string;
  createdAt: string;
  updatedAt: string;
}

// Active layouts map by location
export type ActiveLayoutsMap = Record<LayoutLocation, LayoutTemplate | null>;

// All active layouts by scenario and location
export type AllActiveLayouts = Record<PriceScenario, ActiveLayoutsMap>;

// Element registry for extensibility
export interface ElementDefinition {
  type: ElementType;
  label: string;
  icon: string;
  defaultSettings: Partial<CanvasElement>;
  allowedScenarios: PriceScenario[];
}

// ==========================================================================
// Placeholders - Re-exported from centralized source
// ==========================================================================

// Re-export placeholders from the single source of truth
export {
  availablePlaceholders,
  PLACEHOLDER_KEYS,
  PLACEHOLDER_DESCRIPTIONS,
  type PlaceholderInfo,
  type PlaceholderKey,
} from "@/utils/layoutExporter/placeholders";

/**
 * @deprecated Use PLACEHOLDER_KEYS from '@/utils/layoutExporter/placeholders' instead
 * Kept for backward compatibility
 */
export type Placeholder = string;

/**
 * @deprecated Use PLACEHOLDER_KEYS from '@/utils/layoutExporter/placeholders' instead
 * Kept for backward compatibility - imports from centralized source
 */
export { PLACEHOLDER_KEYS as PLACEHOLDERS } from "@/utils/layoutExporter/placeholders";

// ==========================================================================
// Font Types
// ==========================================================================

// Font group types
export type FontGroup = "default" | "standard" | "google" | "custom";

// Font option structure
export interface FontOption {
  value: string;
  label: string;
  group: FontGroup;
}

// Special value for "Default" font option (inherits from theme)
// Uses a non-empty string because Radix Select doesn't allow empty string values
export const DEFAULT_FONT_VALUE = "__default__";
export const DEFAULT_FONT_LABEL = "Default";

/**
 * Check if a font value is a Google font.
 */
export function isGoogleFont(fontValue: string): boolean {
  if (!fontValue || fontValue === DEFAULT_FONT_VALUE) return false;

  const fonts = window.oppbAdmin?.fonts;
  if (!fonts?.google) return false;

  // Google fonts in our list don't have fallback, just the font name
  return fonts.google.some((font) => font.value === fontValue);
}

/**
 * Get the Google Fonts URL for a font name.
 */
export function getGoogleFontUrl(fontName: string): string {
  const encodedName = fontName.replace(/ /g, "+");
  return `https://fonts.googleapis.com/css2?family=${encodedName}:wght@100;200;300;400;500;600;700;800;900&display=swap`;
}

/**
 * Get all available fonts grouped for select component.
 */
export function getGroupedFontOptions(): { label: string; options: FontOption[] }[] {
  const fonts = window.oppbAdmin?.fonts;

  const groups: { label: string; options: FontOption[] }[] = [
    {
      label: "Default",
      options: [{ value: DEFAULT_FONT_VALUE, label: DEFAULT_FONT_LABEL, group: "default" }],
    },
  ];

  // Standard fonts
  if (fonts?.standard?.length) {
    groups.push({
      label: "Standard",
      options: fonts.standard.map((font) => ({
        value: font.value,
        label: font.label,
        group: "standard" as FontGroup,
      })),
    });
  }

  // Google fonts
  if (fonts?.google?.length) {
    groups.push({
      label: "Google Fonts",
      options: fonts.google.map((font) => ({
        value: font.value,
        label: font.label,
        group: "google" as FontGroup,
      })),
    });
  }

  // Custom fonts
  if (fonts?.custom?.length) {
    groups.push({
      label: "Custom",
      options: fonts.custom.map((font) => ({
        value: font.value,
        label: font.label,
        group: "custom" as FontGroup,
      })),
    });
  }

  return groups;
}

/**
 * Get font CSS value. Returns empty string for default (inherits from theme).
 */
export function getFontCssValue(fontValue: string): string {
  if (!fontValue || fontValue === DEFAULT_FONT_VALUE) {
    return "";
  }

  // For Google fonts, handle fallback appropriately
  if (isGoogleFont(fontValue)) {
    // Check if the font value already includes a fallback (contains comma)
    if (fontValue.includes(",")) {
      // Already has fallback, just wrap the font name in quotes if needed
      const parts = fontValue.split(",").map((p) => p.trim());
      const fontName = parts[0];
      const fallbacks = parts.slice(1).join(", ");
      return `"${fontName}", ${fallbacks}`;
    }

    if (fontValue === "JetBrains Mono") {
      return `"${fontValue}", monospace`;
    }
    if (fontValue === "Caveat") {
      return `"${fontValue}", cursive`;
    }
    // No fallback specified, add sans-serif as default
    return `"${fontValue}", sans-serif`;
  }

  return fontValue;
}

/**
 * Get font family for canvas/Konva rendering.
 * Returns undefined for default (uses canvas default), proper value otherwise.
 * For Google fonts, returns just the font name (Konva handles it).
 */
export function getCanvasFontFamily(fontValue: string): string | undefined {
  if (!fontValue || fontValue === DEFAULT_FONT_VALUE) {
    return undefined;
  }

  // For Google fonts, return just the name without fallback
  // Konva will use its own fallback if the font isn't loaded
  if (isGoogleFont(fontValue)) {
    return fontValue;
  }

  return fontValue;
}

export const getAssetsImageFolder = (): string => {
  return window.oppbAdmin.pluginUrl + "assets/img/";
};
