/**
 * Gallery Section Styles
 *
 * Unified types and utilities for gallery element section styling.
 * Follows the same pattern as elementStyles.ts for consistency.
 */

import type { CSSProperties } from 'react';
import type { CanvasElement } from '../types/constructor';
import { getFontByKey, getFontStyle } from './fonts';

/**
 * Gallery section names for styling
 */
export type GallerySectionName =
  | 'header'
  | 'title'
  | 'span'
  | 'card'
  | 'wrapper';

/**
 * Default values for gallery sections to preserve current Tailwind appearance
 */
export const GALLERY_SECTION_DEFAULTS: Record<
  GallerySectionName,
  CSSProperties
> = {
  header: {
    fontSize: '1.5rem', // text-2xl
    fontWeight: '700', // font-bold
    padding: '0.25rem 0.5rem', // px-1 py-2
    textAlign: 'center',
  },
  title: {
    backgroundColor: '#fefce8', // bg-amber-50
    color: '#1e293b', // text-slate-800
    fontSize: '0.875rem', // text-sm
    fontWeight: '600', // font-semibold
    padding: '0.5rem 0.75rem', // py-2 px-3
    borderRadius: '0.5rem', // rounded-lg
    textAlign: 'center',
  },
  span: {
    backgroundColor: '#334155', // bg-slate-700
    color: '#fef3c7', // text-amber-50
    fontSize: '0.75rem', // text-xs
    fontWeight: '500', // font-medium
    padding: '0.5rem', // py-2 px-2
    borderRadius: '0.5rem', // rounded-lg
    textAlign: 'center',
  },
  card: {
    borderRadius: '0.5rem', // rounded-lg
  },
  wrapper: {
    backgroundColor: 'rgba(0, 0, 0, 0.6)', // bg-black/60
    padding: '0.75rem', // p-3
    borderRadius: '0.75rem', // rounded-xl
    gap: '0.5rem', // gap-2
    backdropFilter: 'blur(4px)', // backdrop-blur-sm
  },
};

/**
 * Get trimmed value from unknown input
 */
const getTrimmedValue = (value: unknown): string => {
  if (value === null || value === undefined) return '';
  if (value === 0) return '0';
  return String(value).trim();
};

/**
 * Normalize a numeric value to include a CSS unit suffix.
 * Handles edge cases:
 * - Complex values with spaces (e.g., "0.5rem 0.75rem") → preserved as-is
 * - Values with existing units (e.g., "1.5rem", "16px") → preserved as-is
 * - Plain numbers (e.g., "0.875", 0.5) → append unit
 * - Zero values ("0", 0) → return "0" (no unit needed)
 * - Negative values (e.g., "-0.5") → append unit
 * - Decimal without leading zero (e.g., ".5") → append unit
 * - CSS functions (e.g., "calc(...)") → preserved as-is
 *
 * @param value - The value to normalize
 * @param unit - The unit to append (e.g., 'rem', 'px')
 * @returns Normalized value with unit, or empty string if invalid
 */
const normalizeWithUnit = (value: unknown, unit: string): string => {
  const trimmed = getTrimmedValue(value);
  if (!trimmed) return '';

  // Zero doesn't need a unit
  if (trimmed === '0') return '0';

  // Complex values (contain spaces) - return as-is (e.g., "0.5rem 0.75rem")
  if (trimmed.includes(' ')) return trimmed;

  // CSS functions (calc, var, etc.) - return as-is
  if (/^(calc|var|min|max|clamp)\(/i.test(trimmed)) return trimmed;

  // Already has a unit (letters or %) at the end - return as-is
  if (/[a-z%]+$/i.test(trimmed)) return trimmed;

  // Handle numbers (including negative and decimals like ".5")
  const num = parseFloat(trimmed);
  if (Number.isFinite(num)) {
    // Zero after parsing
    if (num === 0) return '0';
    return `${num}${unit}`;
  }

  // Fallback: return as-is (shouldn't normally reach here)
  return trimmed;
};

/** Normalize rem values (fontSize, padding, borderRadius, gap) */
const normalizeRemValue = (value: unknown): string =>
  normalizeWithUnit(value, 'rem');

/** Normalize pixel values (for properties that use px) */
const normalizePxValue = (value: unknown): string =>
  normalizeWithUnit(value, 'px');

/**
 * Apply value with default fallback and optional unit normalization
 */
const applyWithDefault = (
  style: CSSProperties,
  prop: keyof CSSProperties,
  value: unknown,
  defaultValue: unknown,
  normalize?: (v: unknown) => string,
): void => {
  const trimmed = normalize ? normalize(value) : getTrimmedValue(value);
  if (trimmed) {
    (style as Record<string, unknown>)[prop] = trimmed;
  } else if (defaultValue !== undefined) {
    (style as Record<string, unknown>)[prop] = defaultValue;
  }
};

/**
 * Apply value only if explicitly set (no default - allows CSS inheritance)
 * with optional unit normalization
 */
const applyIfSet = (
  style: CSSProperties,
  prop: keyof CSSProperties,
  value: unknown,
  normalize?: (v: unknown) => string,
): void => {
  const trimmed = normalize ? normalize(value) : getTrimmedValue(value);
  if (trimmed) {
    (style as Record<string, unknown>)[prop] = trimmed;
  }
};

/**
 * Build CSS style object for gallery header section
 */
export function buildGalleryHeaderStyle(
  element: Partial<CanvasElement>,
): CSSProperties {
  const defaults = GALLERY_SECTION_DEFAULTS.header;
  const style: CSSProperties = {};

  applyIfSet(style, 'backgroundColor', element.galleryHeaderBackgroundColor);
  // Inheritable properties: only apply if explicitly set (allows CSS inheritance from wrapper)
  applyIfSet(style, 'color', element.galleryHeaderColor);
  applyIfSet(
    style,
    'fontSize',
    element.galleryHeaderFontSize,
    normalizeRemValue,
  );
  applyIfSet(style, 'fontWeight', element.galleryHeaderFontWeight);
  // Non-inheritable properties: use defaults
  applyWithDefault(
    style,
    'padding',
    element.galleryHeaderPadding,
    defaults.padding,
    normalizeRemValue,
  );
  applyIfSet(
    style,
    'borderRadius',
    element.galleryHeaderBorderRadius,
    normalizeRemValue,
  );
  applyIfSet(style, 'border', element.galleryHeaderBorder); // Complex value, no normalization

  // Apply font family with font library resolution
  const fontKey = element.galleryHeaderFontFamily;
  if (fontKey) {
    const font = getFontByKey(fontKey);
    if (font) {
      Object.assign(style, getFontStyle(font));
    } else {
      style.fontFamily = fontKey;
    }
  }

  // Dimension properties - only apply if explicitly set (allows CSS defaults)
  applyIfSet(style, 'width', element.galleryHeaderWidth);
  applyIfSet(style, 'height', element.galleryHeaderHeight, normalizePxValue);
  applyIfSet(
    style,
    'minHeight',
    element.galleryHeaderMinHeight,
    normalizePxValue,
  );
  applyIfSet(
    style,
    'maxHeight',
    element.galleryHeaderMaxHeight,
    normalizePxValue,
  );

  // Text alignment with center default
  applyWithDefault(
    style,
    'textAlign',
    element.galleryHeaderTextAlign,
    defaults.textAlign,
  );

  return style;
}

/**
 * Build CSS style object for gallery title section
 */
export function buildGalleryTitleStyle(
  element: Partial<CanvasElement>,
): CSSProperties {
  const defaults = GALLERY_SECTION_DEFAULTS.title;
  const style: CSSProperties = {};

  applyWithDefault(
    style,
    'backgroundColor',
    element.galleryTitleBackgroundColor,
    defaults.backgroundColor,
  );
  // Inheritable properties: only apply if explicitly set (allows CSS inheritance from wrapper)
  applyIfSet(style, 'color', element.galleryTitleColor);
  applyIfSet(
    style,
    'fontSize',
    element.galleryTitleFontSize,
    normalizeRemValue,
  );
  applyIfSet(style, 'fontWeight', element.galleryTitleFontWeight);
  // Non-inheritable properties: use defaults
  applyWithDefault(
    style,
    'padding',
    element.galleryTitlePadding,
    defaults.padding,
    normalizeRemValue,
  );
  applyWithDefault(
    style,
    'borderRadius',
    element.galleryTitleBorderRadius,
    defaults.borderRadius,
    normalizeRemValue,
  );
  applyIfSet(style, 'border', element.galleryTitleBorder); // Complex value, no normalization

  // Apply font family with font library resolution
  const fontKey = element.galleryTitleFontFamily;
  if (fontKey) {
    const font = getFontByKey(fontKey);
    if (font) {
      Object.assign(style, getFontStyle(font));
    } else {
      style.fontFamily = fontKey;
    }
  }

  // Text alignment with center default
  applyWithDefault(
    style,
    'textAlign',
    element.galleryTitleTextAlign,
    defaults.textAlign,
  );

  return style;
}

/**
 * Build CSS style object for gallery span items
 */
export function buildGallerySpanStyle(
  element: Partial<CanvasElement>,
): CSSProperties {
  const defaults = GALLERY_SECTION_DEFAULTS.span;
  const style: CSSProperties = {};

  applyWithDefault(
    style,
    'backgroundColor',
    element.gallerySpanBackgroundColor,
    defaults.backgroundColor,
  );
  // Inheritable properties: only apply if explicitly set (allows CSS inheritance from wrapper)
  applyIfSet(style, 'color', element.gallerySpanColor);
  applyIfSet(style, 'fontSize', element.gallerySpanFontSize, normalizeRemValue);
  applyIfSet(style, 'fontWeight', element.gallerySpanFontWeight);
  // Non-inheritable properties: use defaults
  applyWithDefault(
    style,
    'padding',
    element.gallerySpanPadding,
    defaults.padding,
    normalizeRemValue,
  );
  applyWithDefault(
    style,
    'borderRadius',
    element.gallerySpanBorderRadius,
    defaults.borderRadius,
    normalizeRemValue,
  );
  applyIfSet(style, 'border', element.gallerySpanBorder); // Complex value, no normalization

  // Apply font family with font library resolution (fallback to galleryTextFontFamily for legacy support)
  const fontKey =
    element.gallerySpanFontFamily || element.galleryTextFontFamily;
  if (fontKey) {
    const font = getFontByKey(fontKey);
    if (font) {
      Object.assign(style, getFontStyle(font));
    } else {
      style.fontFamily = fontKey;
    }
  }

  // Text alignment with center default
  applyWithDefault(
    style,
    'textAlign',
    element.gallerySpanTextAlign,
    defaults.textAlign,
  );

  return style;
}

/**
 * Build CSS style object for gallery span grid container
 */
export function buildGallerySpanGridStyle(
  element: Partial<CanvasElement>,
): CSSProperties {
  const columns = getGalleryGridColumns(element, 'span');
  const gap = normalizeRemValue(element.gallerySpanGap) || '0.5rem';

  return {
    display: 'grid',
    gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
    gap,
  };
}

/**
 * Build CSS style object for gallery card items
 */
export function buildGalleryCardStyle(
  element: Partial<CanvasElement>,
): CSSProperties {
  const defaults = GALLERY_SECTION_DEFAULTS.card;
  const style: CSSProperties = {};

  applyWithDefault(
    style,
    'backgroundColor',
    element.galleryCardBackgroundColor,
    undefined,
  );
  applyWithDefault(
    style,
    'borderRadius',
    element.galleryCardBorderRadius,
    defaults.borderRadius,
    normalizeRemValue,
  );
  applyIfSet(style, 'border', element.galleryCardBorder); // Complex value, no normalization

  // Dimension properties - only apply if explicitly set
  applyIfSet(style, 'width', element.galleryCardWidth);
  applyIfSet(style, 'height', element.galleryCardHeight, normalizePxValue);
  applyIfSet(
    style,
    'minHeight',
    element.galleryCardMinHeight,
    normalizePxValue,
  );
  applyIfSet(style, 'aspectRatio', element.galleryCardAspectRatio);

  return style;
}

/**
 * Build CSS style object for gallery card title overlay
 */
export function buildGalleryCardTitleStyle(
  element: Partial<CanvasElement>,
): CSSProperties {
  const style: CSSProperties = {};

  // Inheritable properties: only apply if explicitly set (allows CSS inheritance from wrapper)
  // Note: card titles typically need white text for visibility over images
  applyIfSet(style, 'color', element.galleryCardTitleColor);
  applyIfSet(
    style,
    'fontSize',
    element.galleryCardTitleFontSize,
    normalizeRemValue,
  );
  applyIfSet(style, 'fontWeight', element.galleryCardTitleFontWeight);

  if (element.galleryCardTitleBackgroundColor) {
    style.backgroundColor = element.galleryCardTitleBackgroundColor;
  }

  // Handle text shadow - complex value, no normalization
  const shadow = element.galleryCardTitleShadow;
  if (shadow) {
    style.textShadow = shadow;
  } else {
    // Default drop-shadow-lg equivalent for visibility over images
    style.filter =
      'drop-shadow(0 10px 8px rgb(0 0 0 / 0.04)) drop-shadow(0 4px 3px rgb(0 0 0 / 0.1))';
  }

  // Apply font family from galleryTextFontFamily for legacy support
  const fontKey = element.galleryTextFontFamily;
  if (fontKey) {
    const font = getFontByKey(fontKey);
    if (font) {
      Object.assign(style, getFontStyle(font));
    } else {
      style.fontFamily = fontKey;
    }
  }

  return style;
}

/**
 * Build CSS style object for gallery cards grid container
 */
export function buildGalleryCardGridStyle(
  element: Partial<CanvasElement>,
): CSSProperties {
  const columns = getGalleryGridColumns(element, 'card');
  const gap = normalizeRemValue(element.galleryCardGap) || '0.5rem';

  return {
    display: 'grid',
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gap,
    width: '100%',
  };
}

/**
 * Get grid columns with fallback to legacy galleryColumns
 */
export function getGalleryGridColumns(
  element: Partial<CanvasElement>,
  section: 'span' | 'card',
): number {
  if (section === 'span') {
    return element.gallerySpanColumns ?? element.galleryColumns ?? 3;
  }
  // For cards, use galleryCardColumns with fallback to legacy galleryColumns
  return element.galleryCardColumns ?? element.galleryColumns ?? 3;
}

/**
 * All gallery section style property names for iteration
 */
export const GALLERY_SECTION_STYLE_PROPS = [
  // Header
  'galleryHeaderBackgroundColor',
  'galleryHeaderColor',
  'galleryHeaderFontFamily',
  'galleryHeaderFontSize',
  'galleryHeaderFontWeight',
  'galleryHeaderPadding',
  'galleryHeaderBorderRadius',
  'galleryHeaderBorder',
  'galleryHeaderWidth',
  'galleryHeaderHeight',
  'galleryHeaderMinHeight',
  'galleryHeaderMaxHeight',
  'galleryHeaderTextAlign',
  // Title
  'galleryTitleBackgroundColor',
  'galleryTitleColor',
  'galleryTitleFontFamily',
  'galleryTitleFontSize',
  'galleryTitleFontWeight',
  'galleryTitlePadding',
  'galleryTitleBorderRadius',
  'galleryTitleBorder',
  'galleryTitleTextAlign',
  // Spans
  'gallerySpanBackgroundColor',
  'gallerySpanColor',
  'gallerySpanFontFamily',
  'gallerySpanFontSize',
  'gallerySpanFontWeight',
  'gallerySpanPadding',
  'gallerySpanBorderRadius',
  'gallerySpanBorder',
  'gallerySpanGap',
  'gallerySpanColumns',
  'gallerySpanTextAlign',
  // Cards
  'galleryCardBackgroundColor',
  'galleryCardBorderRadius',
  'galleryCardBorder',
  'galleryCardGap',
  'galleryCardColumns',
  'galleryCardTitleColor',
  'galleryCardTitleBackgroundColor',
  'galleryCardTitleFontSize',
  'galleryCardTitleFontWeight',
  'galleryCardTitleShadow',
  'galleryCardWidth',
  'galleryCardHeight',
  'galleryCardMinHeight',
  'galleryCardAspectRatio',
] as const;

export type GallerySectionStyleProp =
  (typeof GALLERY_SECTION_STYLE_PROPS)[number];
