/**
 * Constructor Types
 *
 * Shared types for the constructor page and related UI elements.
 * Used in constructor.tsx, page_elements pages, and element-type-defaults pages.
 */

import type { ElementStyleProperties } from '../lib/elementStyles';
import type { ElementEffectProperties } from '../lib/elementEffects';

/**
 * Element types available in the constructor canvas.
 * These map to element_type_defaults records in the database.
 * Using TEXT in the database allows adding new types without migrations.
 */
export type CanvasElementType =
  | 'navigation_next' // Forward navigation button
  | 'navigation_prev' // Back navigation button
  | 'spot' // Hotspot/clickable area
  | 'description' // Text description block
  | 'tooltip' // Hover tooltip
  | 'gallery' // Image gallery
  | 'carousel' // Image carousel
  | 'logo' // Logo element
  | 'video_player' // Video player
  | 'audio_player' // Audio player
  | 'popup'; // Popup/modal

/**
 * Navigation button direction
 */
export type NavigationButtonKind = 'forward' | 'back';

/**
 * Gallery card item
 */
export interface GalleryCard {
  id: string;
  imageUrl: string;
  title: string;
  description: string;
}

/**
 * Gallery info span (brief note badge)
 */
export interface GalleryInfoSpan {
  id: string;
  text: string;
}

/**
 * Carousel slide item
 */
export interface CarouselSlide {
  id: string;
  imageUrl: string;
  caption: string;
}

/**
 * Base canvas element with common positioning and styling fields.
 * Extends ElementStyleProperties for CSS styling and ElementEffectProperties for effects.
 */
export interface BaseCanvasElement
  extends ElementStyleProperties,
    ElementEffectProperties {
  id: string;
  type: CanvasElementType | string;
  label?: string;
  xPercent?: number;
  yPercent?: number;
  iconUrl?: string;
  appearDelaySec?: number;
  appearDurationSec?: number | null;
}

/**
 * Full canvas element with all content fields
 */
export interface CanvasElement extends BaseCanvasElement {
  type: CanvasElementType;
  label: string;
  xPercent: number;
  yPercent: number;
  iconUrl?: string;
  mediaUrl?: string;
  mediaAutoplay?: boolean;
  mediaLoop?: boolean;
  mediaMuted?: boolean;
  backgroundImageUrl?: string;
  videoUrl?: string;
  audioUrl?: string;
  galleryCards?: GalleryCard[];
  // Gallery header settings
  galleryHeaderImageUrl?: string;
  galleryTitle?: string;
  galleryInfoSpans?: GalleryInfoSpan[];
  galleryColumns?: number;
  galleryTitleFontFamily?: string;
  galleryTextFontFamily?: string;
  carouselSlides?: CarouselSlide[];
  carouselCaptionFontFamily?: string;
  carouselPrevIconUrl?: string;
  carouselNextIconUrl?: string;
  tooltipTitle?: string;
  tooltipText?: string;
  tooltipTitleFontFamily?: string;
  tooltipTextFontFamily?: string;
  descriptionTitle?: string;
  descriptionText?: string;
  descriptionTitleFontSize?: string;
  descriptionTextFontSize?: string;
  descriptionTitleFontFamily?: string;
  descriptionTextFontFamily?: string;
  descriptionTitleColor?: string;
  descriptionTextColor?: string;
  navLabel?: string;
  navLabelFontFamily?: string;
  navType?: NavigationButtonKind;
  navDisabled?: boolean;
  /** @deprecated Use targetPageSlug instead - IDs change when copied between environments */
  targetPageId?: string;
  /** Target page slug for navigation - slugs are consistent across environments */
  targetPageSlug?: string;
  transitionVideoUrl?: string;
  transitionReverseMode?: 'auto_reverse' | 'separate_video';
  reverseVideoUrl?: string;
  transitionDurationSec?: number;
  // Gallery Carousel Settings
  galleryCarouselPrevIconUrl?: string;
  galleryCarouselNextIconUrl?: string;
  galleryCarouselBackIconUrl?: string;
  galleryCarouselBackLabel?: string;
  // Prev button position (percentage)
  galleryCarouselPrevX?: number;
  galleryCarouselPrevY?: number;
  // Next button position (percentage)
  galleryCarouselNextX?: number;
  galleryCarouselNextY?: number;
  // Back button position (percentage)
  galleryCarouselBackX?: number;
  galleryCarouselBackY?: number;
  // Button dimensions (CSS values like '48px', '3rem')
  galleryCarouselPrevWidth?: string;
  galleryCarouselPrevHeight?: string;
  galleryCarouselNextWidth?: string;
  galleryCarouselNextHeight?: string;
  galleryCarouselBackWidth?: string;
  galleryCarouselBackHeight?: string;
}

/**
 * Constructor schema containing elements array
 */
export interface ConstructorSchema {
  elements?: CanvasElement[];
}

/**
 * UI element default settings from database
 */
export interface UiElementDefault {
  id: string;
  element_type?: string;
  is_active?: boolean;
  default_settings_json?: string | Record<string, unknown>;
}

/**
 * Project asset for constructor asset selection
 */
export interface ConstructorAsset {
  id: string;
  name?: string;
  asset_type?: 'image' | 'video' | 'audio' | 'file';
  type?:
    | 'icon'
    | 'background_image'
    | 'audio'
    | 'video'
    | 'transition'
    | 'logo'
    | 'favicon'
    | 'document'
    | 'general';
  cdn_url?: string | null;
  storage_key?: string | null;
}

/**
 * Asset option for select dropdowns
 */
export interface AssetOption {
  value: string;
  label: string;
}

/**
 * All valid canvas element types
 */
const CANVAS_ELEMENT_TYPES: CanvasElementType[] = [
  'navigation_next',
  'navigation_prev',
  'spot',
  'description',
  'tooltip',
  'gallery',
  'carousel',
  'logo',
  'video_player',
  'audio_player',
  'popup',
];

/**
 * Type guard for CanvasElementType
 */
export function isCanvasElementType(value: string): value is CanvasElementType {
  return CANVAS_ELEMENT_TYPES.includes(value as CanvasElementType);
}

/**
 * Element default from either element_type_defaults or project_element_defaults
 * Normalizes field names for consistent usage
 */
export interface NormalizedElementDefault {
  id: string;
  element_type: string;
  name?: string;
  sort_order?: number;
  settings: Partial<CanvasElement>;
}

/**
 * Normalize element default from API response
 * Handles both global (default_settings_json) and project (settings_json) defaults
 */
export function normalizeElementDefault(
  row: Record<string, unknown>,
): NormalizedElementDefault | null {
  const elementType = String(row.element_type || '').trim();
  if (!elementType) return null;

  // Handle both field names: settings_json (project) and default_settings_json (global)
  const rawSettings = row.settings_json ?? row.default_settings_json;
  let settings: Partial<CanvasElement> = {};

  if (typeof rawSettings === 'string') {
    try {
      settings = JSON.parse(rawSettings);
    } catch {
      settings = {};
    }
  } else if (rawSettings && typeof rawSettings === 'object') {
    settings = rawSettings as Partial<CanvasElement>;
  }

  return {
    id: String(row.id || ''),
    element_type: elementType,
    name: row.name ? String(row.name) : undefined,
    sort_order: typeof row.sort_order === 'number' ? row.sort_order : 0,
    settings,
  };
}

/**
 * Build defaults map from normalized defaults array
 */
export function buildElementDefaultsMap(
  defaults: NormalizedElementDefault[],
): Partial<Record<CanvasElementType, Partial<CanvasElement>>> {
  const map: Partial<Record<CanvasElementType, Partial<CanvasElement>>> = {};

  for (const def of defaults) {
    if (isCanvasElementType(def.element_type)) {
      map[def.element_type] = def.settings;
    }
  }

  return map;
}

// ============================================================================
// Grouped Props for ElementEditorPanel
// ============================================================================

/**
 * Editor layout props: panel position and collapse state
 */
export interface EditorLayoutProps {
  elementEditorRef: React.RefObject<HTMLDivElement | null>;
  position: { x: number; y: number };
  isCollapsed: boolean;
  onToggleCollapse: () => void;
  onDragStart: (event: React.MouseEvent) => void;
}

/**
 * Editor state props: tabs and title
 */
export interface EditorStateProps {
  title: string;
  activeTab: 'general' | 'css' | 'effects';
  onTabChange: (tab: 'general' | 'css' | 'effects') => void;
}

/**
 * Selected element props
 */
export interface EditorElementProps {
  selectedElement: CanvasElement | null;
  selectedMenuItem:
    | 'none'
    | 'background_image'
    | 'background_video'
    | 'background_audio'
    | 'create_transition';
  onRemoveElement: () => void;
  onUpdateElement: (patch: Partial<CanvasElement>) => void;
}

/**
 * Background settings props
 */
export interface EditorBackgroundProps {
  backgroundImageUrl: string;
  backgroundVideoUrl: string;
  backgroundAudioUrl: string;
  onBackgroundImageChange: (value: string) => void;
  onBackgroundVideoChange: (value: string) => void;
  onBackgroundAudioChange: (value: string) => void;
}

/**
 * Transition creation props
 */
export interface EditorTransitionProps {
  newTransitionName: string;
  newTransitionVideoUrl: string;
  newTransitionSupportsReverse: boolean;
  isCreatingTransition: boolean;
  onNewTransitionNameChange: (value: string) => void;
  onNewTransitionVideoUrlChange: (value: string) => void;
  onNewTransitionSupportsReverseChange: (value: boolean) => void;
  onCreateTransition: () => void;
}

/**
 * Duration notes props
 */
export interface EditorDurationNotesProps {
  backgroundVideoDurationNote: string;
  backgroundAudioDurationNote: string;
  newTransitionDurationNote: string;
  selectedMediaDurationNote: string;
  selectedTransitionDurationNote: string;
}

/**
 * Asset options for dropdowns
 */
export interface EditorAssetOptionsProps {
  backgroundImageAssetOptions: AssetOption[];
  videoAssetOptions: AssetOption[];
  audioAssetOptions: AssetOption[];
  transitionVideoAssetOptions: AssetOption[];
  iconAssetOptions: AssetOption[];
  imageAssetOptions: AssetOption[];
}

/**
 * Navigation settings props
 */
export interface EditorNavigationProps {
  allowedNavigationTypes: Array<'navigation_next' | 'navigation_prev'>;
  pages: Array<{
    id: string;
    name?: string;
    slug?: string;
    sort_order?: number;
  }>;
  activePageId: string;
  onPreviewTransition: (direction: 'forward' | 'back') => void;
  normalizeNavigationType: (
    element: CanvasElement,
    nextType: 'navigation_next' | 'navigation_prev',
  ) => CanvasElement;
}

/**
 * Gallery/Carousel operations props
 */
export interface EditorCollectionOpsProps {
  galleryCards: {
    add: () => void;
    update: (cardId: string, patch: Partial<GalleryCard>) => void;
    remove: (cardId: string) => void;
  };
  galleryInfoSpans: {
    add: () => void;
    update: (spanId: string, text: string) => void;
    remove: (spanId: string) => void;
  };
  carouselSlides: {
    add: () => void;
    update: (slideId: string, patch: Partial<CarouselSlide>) => void;
    remove: (slideId: string) => void;
  };
}

/**
 * Media utilities props
 */
export interface EditorMediaUtilsProps {
  getDuration: (url: string) => number | undefined;
}
