/**
 * Element Settings Types
 *
 * Shared types for element settings form components.
 * Used across element-type-defaults, project-element-defaults, and constructor pages.
 */

import type { ElementStyleProperties } from '../../lib/elementStyles';
import type { ElementEffectProperties } from '../../lib/elementEffects';
import type {
  CanvasElement,
  CanvasElementType,
  GalleryCard,
  GalleryInfoSpan,
  CarouselSlide,
  AssetOption,
} from '../../types/constructor';

/**
 * Context for element settings components.
 * Determines available fields and behaviors.
 */
export type ElementSettingsContext =
  | 'global' // element-type-defaults page - plain text inputs
  | 'project' // project-element-defaults page - plain text inputs
  | 'constructor'; // constructor page - asset selectors available

/**
 * Props for CSS style settings section
 */
export interface StyleSettingsSectionProps {
  values: ElementStyleProperties;
  onChange: (prop: keyof ElementStyleProperties, value: string) => void;
}

/**
 * Form values for effects settings section (uses strings for form inputs)
 */
export interface EffectsSettingsFormValues {
  appearAnimation?: string;
  appearAnimationDuration?: string;
  appearAnimationEasing?: string;
  hoverScale?: string;
  hoverOpacity?: string;
  hoverBackgroundColor?: string;
  hoverColor?: string;
  hoverBoxShadow?: string;
  hoverTransitionDuration?: string;
  focusScale?: string;
  focusOpacity?: string;
  focusOutline?: string;
  focusBoxShadow?: string;
  activeScale?: string;
  activeOpacity?: string;
  activeBackgroundColor?: string;
}

/**
 * Props for effects settings section
 */
export interface EffectsSettingsSectionProps {
  values: EffectsSettingsFormValues;
  onChange: (prop: keyof EffectsSettingsFormValues, value: string) => void;
}

/**
 * Props for common settings section (label, position, appear timing)
 */
export interface CommonSettingsSectionProps {
  label: string;
  xPercent: string;
  yPercent: string;
  appearDelaySec: string;
  appearDurationSec: string;
  onChange: (field: string, value: string) => void;
  showLabel?: boolean;
  showPosition?: boolean;
}

/**
 * Props for navigation element settings
 */
export interface NavigationSettingsSectionProps {
  iconUrl: string;
  navLabel: string;
  navLabelFontFamily: string;
  navType: 'forward' | 'back';
  navDisabled: boolean;
  targetPageId: string;
  targetPageSlug: string;
  transitionVideoUrl: string;
  transitionReverseMode: 'auto_reverse' | 'separate_video';
  reverseVideoUrl: string;
  onChange: (field: string, value: string | boolean) => void;
  context: ElementSettingsContext;
  iconAssetOptions?: AssetOption[];
  transitionVideoAssetOptions?: AssetOption[];
  pageOptions?: { value: string; label: string }[];
}

/**
 * Props for tooltip element settings
 */
export interface TooltipSettingsSectionProps {
  iconUrl: string;
  tooltipTitle: string;
  tooltipText: string;
  tooltipTitleFontFamily: string;
  tooltipTextFontFamily: string;
  onChange: (field: string, value: string) => void;
  context: ElementSettingsContext;
  iconAssetOptions?: AssetOption[];
}

/**
 * Props for description element settings
 */
export interface DescriptionSettingsSectionProps {
  iconUrl: string;
  descriptionTitle: string;
  descriptionText: string;
  descriptionTitleFontSize: string;
  descriptionTextFontSize: string;
  descriptionTitleFontFamily: string;
  descriptionTextFontFamily: string;
  descriptionTitleColor: string;
  descriptionTextColor: string;
  onChange: (field: string, value: string) => void;
  context: ElementSettingsContext;
  iconAssetOptions?: AssetOption[];
}

/**
 * Props for media (video/audio player) element settings
 */
export interface MediaSettingsSectionProps {
  elementType: 'video_player' | 'audio_player';
  mediaUrl: string;
  mediaAutoplay: boolean;
  mediaLoop: boolean;
  mediaMuted: boolean;
  onChange: (field: string, value: string | boolean) => void;
  context: ElementSettingsContext;
  videoAssetOptions?: AssetOption[];
  audioAssetOptions?: AssetOption[];
}

/**
 * Props for gallery element settings (non-compact version)
 * Used in element-type-defaults and project-element-defaults pages
 */
export interface GallerySettingsSectionProps {
  galleryCards: GalleryCard[];
  galleryTitleFontFamily: string;
  galleryTextFontFamily: string;
  onAddCard: () => void;
  onRemoveCard: (cardId: string) => void;
  onUpdateCard: (
    cardId: string,
    field: keyof GalleryCard,
    value: string,
  ) => void;
  onChange: (field: string, value: string) => void;
  context: ElementSettingsContext;
  imageAssetOptions?: AssetOption[];
}

/**
 * Props for gallery element settings (compact version)
 * Used in constructor sidebar with full header/spans/cards support
 */
export interface GallerySettingsSectionCompactProps {
  // Header settings
  galleryHeaderImageUrl: string;
  galleryTitle: string;
  galleryInfoSpans: GalleryInfoSpan[];
  galleryColumns: number;
  // Font settings
  galleryTitleFontFamily: string;
  galleryTextFontFamily: string;
  // Cards
  galleryCards: GalleryCard[];
  imageAssetOptions: AssetOption[];
  // Header handlers
  onUpdateHeader: (patch: {
    galleryHeaderImageUrl?: string;
    galleryTitle?: string;
    galleryColumns?: number;
    galleryTitleFontFamily?: string;
    galleryTextFontFamily?: string;
  }) => void;
  // Info span handlers
  onAddInfoSpan: () => void;
  onUpdateInfoSpan: (spanId: string, text: string) => void;
  onRemoveInfoSpan: (spanId: string) => void;
  // Card handlers
  onAddCard: () => void;
  onUpdateCard: (cardId: string, patch: Partial<GalleryCard>) => void;
  onRemoveCard: (cardId: string) => void;
}

/**
 * Props for carousel element settings
 */
export interface CarouselSettingsSectionProps {
  carouselPrevIconUrl: string;
  carouselNextIconUrl: string;
  carouselCaptionFontFamily: string;
  carouselSlides: CarouselSlide[];
  onAddSlide: () => void;
  onRemoveSlide: (slideId: string) => void;
  onUpdateSlide: (
    slideId: string,
    field: keyof CarouselSlide,
    value: string,
  ) => void;
  onChange: (field: string, value: string) => void;
  context: ElementSettingsContext;
  iconAssetOptions?: AssetOption[];
  imageAssetOptions?: AssetOption[];
}

/**
 * Props for element settings tabs component
 */
export interface ElementSettingsTabsProps {
  activeTab: string;
  onTabChange: (tabId: string) => void;
  tabs: { id: string; label: string }[];
}

/**
 * Props for gallery carousel settings section (constructor)
 */
export interface GalleryCarouselSettingsSectionProps {
  prevIconUrl: string;
  nextIconUrl: string;
  backIconUrl: string;
  backLabel: string;
  onChange: (
    field:
      | 'galleryCarouselPrevIconUrl'
      | 'galleryCarouselNextIconUrl'
      | 'galleryCarouselBackIconUrl'
      | 'galleryCarouselBackLabel',
    value: string,
  ) => void;
  iconAssetOptions: AssetOption[];
}

/**
 * Value normalization helpers
 */
export const clampPercent = (value: string): number => {
  const parsed = Number(value);
  if (!Number.isFinite(parsed)) return 0;
  return Math.min(Math.max(parsed, 0), 100);
};

export const parseNullableNumber = (value: string): number | null => {
  if (!value.trim()) return null;
  const parsed = Number(value);
  if (!Number.isFinite(parsed) || parsed < 0) return null;
  return parsed;
};

export const extractNumericValue = (value: unknown): string => {
  const normalized = String(value ?? '').trim();
  if (!normalized) return '';
  const matched = normalized.match(/-?\d*\.?\d+/);
  return matched ? matched[0] : '';
};

export const normalizeNumberString = (value: string): string => {
  const normalized = String(value || '').trim();
  if (!normalized) return '';
  const parsed = Number(normalized);
  if (!Number.isFinite(parsed)) return '';
  return String(parsed);
};

export const toOptionalTrimmed = (value: string): string | undefined => {
  const normalized = String(value || '').trim();
  return normalized ? normalized : undefined;
};

export const toUnitValue = (
  value: string,
  unit: 'vw' | 'vh' | 'px',
): string | undefined => {
  const normalized = normalizeNumberString(value);
  return normalized ? `${normalized}${unit}` : undefined;
};
