/**
 * AI Payload Optimizer
 *
 * Prepares canvas elements and container settings for AI generation
 * by removing unnecessary data and simplifying responsive values.
 */

import type {
  CanvasElement,
  ContainerSettings,
  ResponsiveValue,
  ResponsiveSpacing,
  ResponsiveTypographySettings,
  ResponsiveBorderSettings,
  DecimalSettings,
} from "@/types";

/**
 * Simplified element type for AI payload
 * Contains only essential information needed for layout generation
 */
export interface SimplifiedElement {
  type: string;
  name: string;
  position: { x: number; y: number };
  size: { width: number; height: number };
  rotation?: number;
  color: string;
  backgroundColor?: string;
  opacity?: number;
  typography: SimplifiedTypography;
  border?: SimplifiedBorder;
  animation?: { type: string; duration?: number; delay?: number; direction?: string };
  // Type-specific properties
  showCurrency?: boolean; // Whether to show currency symbol with this price element
  decimal?: unknown;
  lineThrough?: unknown;
  symbol?: string;
  format?: string;
  customFormat?: string;
  text?: string;
  textAlign?: string;
  displayMode?: string;
  separator?: string;
  prefixText?: string;
  backgroundImage?: string;
  backgroundSize?: string;
  backgroundPosition?: string;
}

interface SimplifiedTypography {
  fontFamily: string;
  fontSize: number;
  fontWeight: number;
  fontStyle?: string;
  lineHeight?: number;
  letterSpacing?: number;
  textTransform?: string;
  textDecoration?: string;
}

interface SimplifiedBorder {
  width: number;
  style: string;
  color: string;
  radius: number;
}

interface SimplifiedContainerSettings {
  border?: SimplifiedBorder;
  backgroundColor?: string;
  backgroundImage?: string;
  backgroundSize?: string;
  backgroundPosition?: string;
  backgroundRepeat?: string;
}

/**
 * Extract desktop value from responsive value
 */
function getDesktopValue<T>(value: ResponsiveValue<T> | T): T {
  if (typeof value === "object" && value !== null && "desktop" in value) {
    return (value as ResponsiveValue<T>).desktop;
  }
  return value as T;
}

/**
 * Round a number to whole integer
 */
function roundNumber(value: number): number {
  return Math.round(value);
}

/**
 * Simplify typography settings - extract desktop values only
 */
function simplifyTypography(typography: ResponsiveTypographySettings): SimplifiedTypography {
  const result: SimplifiedTypography = {
    fontFamily: typography.fontFamily,
    fontSize: roundNumber(getDesktopValue(typography.fontSize)),
    fontWeight: getDesktopValue(typography.fontWeight),
  };

  // Only include non-default values
  if (typography.fontStyle !== "normal") {
    result.fontStyle = typography.fontStyle;
  }
  if (typography.lineHeight !== 1) {
    result.lineHeight = typography.lineHeight;
  }
  const letterSpacing = getDesktopValue(typography.letterSpacing);
  if (letterSpacing !== 0) {
    result.letterSpacing = roundNumber(letterSpacing);
  }
  if (typography.textTransform !== "none") {
    result.textTransform = typography.textTransform;
  }
  if (typography.textDecoration !== "none") {
    result.textDecoration = typography.textDecoration;
  }

  return result;
}

/**
 * Simplify partial typography (for decimal settings)
 */
function simplifyPartialTypography(typography: Partial<ResponsiveTypographySettings>): Partial<SimplifiedTypography> {
  const result: Partial<SimplifiedTypography> = {};

  if (typography.fontFamily) {
    result.fontFamily = typography.fontFamily;
  }
  if (typography.fontSize !== undefined) {
    result.fontSize = roundNumber(getDesktopValue(typography.fontSize));
  }
  if (typography.fontWeight !== undefined) {
    result.fontWeight = getDesktopValue(typography.fontWeight);
  }
  if (typography.fontStyle && typography.fontStyle !== "normal") {
    result.fontStyle = typography.fontStyle;
  }
  if (typography.lineHeight !== undefined && typography.lineHeight !== 1) {
    result.lineHeight = typography.lineHeight;
  }
  if (typography.letterSpacing !== undefined) {
    const letterSpacing = getDesktopValue(typography.letterSpacing);
    if (letterSpacing !== 0) {
      result.letterSpacing = roundNumber(letterSpacing);
    }
  }
  if (typography.textTransform && typography.textTransform !== "none") {
    result.textTransform = typography.textTransform;
  }
  if (typography.textDecoration && typography.textDecoration !== "none") {
    result.textDecoration = typography.textDecoration;
  }

  return result;
}

/**
 * Simplified decimal settings
 */
interface SimplifiedDecimalSettings {
  show: boolean;
  separator?: string;
  typography?: Partial<SimplifiedTypography>;
  position?: string;
  absoluteOffset?: { x: number; y: number };
}

/**
 * Simplify decimal settings - extract desktop typography values
 */
function simplifyDecimal(decimal: DecimalSettings): SimplifiedDecimalSettings {
  const result: SimplifiedDecimalSettings = {
    show: decimal.show,
  };

  // Only include non-default values
  if (decimal.separator !== "point") {
    result.separator = decimal.separator;
  }
  if (decimal.typography && Object.keys(decimal.typography).length > 0) {
    const simplifiedTypo = simplifyPartialTypography(decimal.typography);
    if (Object.keys(simplifiedTypo).length > 0) {
      result.typography = simplifiedTypo;
    }
  }
  if (decimal.position !== "inline") {
    result.position = decimal.position;
  }
  if (decimal.position === "absolute" && decimal.absoluteOffset) {
    result.absoluteOffset = {
      x: roundNumber(decimal.absoluteOffset.x),
      y: roundNumber(decimal.absoluteOffset.y),
    };
  }

  return result;
}

/**
 * Simplify border settings - extract desktop values only
 */
function simplifyBorder(border: ResponsiveBorderSettings): SimplifiedBorder | undefined {
  const width = getDesktopValue(border.width);

  // If no border width, don't include border at all
  if (width === 0) {
    return undefined;
  }

  return {
    width: roundNumber(width),
    style: border.style,
    color: border.color,
    radius: roundNumber(border.radius),
  };
}

/**
 * Check if spacing has any non-zero values
 */
function hasSpacingValues(spacing: ResponsiveSpacing): boolean {
  return (
    getDesktopValue(spacing.top) !== 0 ||
    getDesktopValue(spacing.right) !== 0 ||
    getDesktopValue(spacing.bottom) !== 0 ||
    getDesktopValue(spacing.left) !== 0
  );
}

/**
 * Simplify a single canvas element for AI payload
 */
function simplifyElement(element: CanvasElement): SimplifiedElement {
  const simplified: SimplifiedElement = {
    type: element.type,
    name: element.name,
    position: {
      x: roundNumber(element.position.x),
      y: roundNumber(element.position.y),
    },
    size: {
      width: roundNumber(element.size.width),
      height: roundNumber(element.size.height),
    },
    color: element.color,
    typography: simplifyTypography(element.typography),
  };

  // Only include rotation if non-zero
  if (element.rotation !== 0) {
    simplified.rotation = roundNumber(element.rotation);
  }

  // Only include backgroundColor if not transparent/empty
  if (element.backgroundColor && element.backgroundColor !== "transparent" && element.backgroundColor !== "") {
    simplified.backgroundColor = element.backgroundColor;
  }

  // Only include opacity if not 1
  if (element.opacity !== 1) {
    simplified.opacity = element.opacity;
  }

  // Only include border if it has width
  const border = simplifyBorder(element.border);
  if (border) {
    simplified.border = border;
  }

  // Only include animation if type is not "none"
  if (element.animation && element.animation.type !== "none") {
    simplified.animation = {
      type: element.animation.type,
    };
    if (element.animation.duration !== 300) {
      simplified.animation.duration = element.animation.duration;
    }
    if (element.animation.delay !== 0) {
      simplified.animation.delay = element.animation.delay;
    }
    if (element.animation.direction) {
      simplified.animation.direction = element.animation.direction;
    }
  }

  // Type-specific properties
  switch (element.type) {
    case "regularPrice":
    case "salePrice":
      if ("decimal" in element && element.decimal) {
        // Extract showCurrency to main element level (it's not related to decimals)
        if (element.decimal.showCurrency) {
          simplified.showCurrency = true;
        }
        simplified.decimal = simplifyDecimal(element.decimal);
      }
      if ("lineThrough" in element && element.lineThrough?.enabled) {
        simplified.lineThrough = element.lineThrough;
      }
      break;

    case "currencySymbol":
      if ("symbol" in element) {
        simplified.symbol = element.symbol;
      }
      break;

    case "discountBadge":
      if ("format" in element) {
        simplified.format = element.format;
        if (element.format === "custom" && "customFormat" in element) {
          simplified.customFormat = element.customFormat;
        }
      }
      break;

    case "text":
      if ("text" in element) {
        simplified.text = element.text;
      }
      if ("textAlign" in element && element.textAlign !== "left") {
        simplified.textAlign = element.textAlign;
      }
      // Only include background image properties if backgroundImage exists
      if ("backgroundImage" in element && element.backgroundImage) {
        simplified.backgroundImage = element.backgroundImage;
        if ("backgroundSize" in element) {
          simplified.backgroundSize = element.backgroundSize;
        }
        if ("backgroundPosition" in element) {
          simplified.backgroundPosition = element.backgroundPosition;
        }
      }
      break;

    case "variablePriceRange":
      if ("displayMode" in element) {
        simplified.displayMode = element.displayMode;
      }
      if ("separator" in element) {
        simplified.separator = element.separator;
      }
      if ("prefixText" in element) {
        simplified.prefixText = element.prefixText;
      }
      if ("minDecimal" in element && element.minDecimal) {
        (simplified as Record<string, unknown>).minDecimal = simplifyDecimal(element.minDecimal);
      }
      if ("maxDecimal" in element && element.maxDecimal) {
        (simplified as Record<string, unknown>).maxDecimal = simplifyDecimal(element.maxDecimal);
      }
      if ("lineThrough" in element && element.lineThrough?.enabled) {
        simplified.lineThrough = element.lineThrough;
      }
      break;
  }

  return simplified;
}

/**
 * Simplify container settings for AI payload
 */
function simplifyContainerSettings(settings: ContainerSettings): SimplifiedContainerSettings {
  const simplified: SimplifiedContainerSettings = {};

  // Border - only if has width
  const border = simplifyBorder(settings.border);
  if (border) {
    simplified.border = border;
  }

  // Background color - only if not transparent/empty
  if (settings.backgroundColor && settings.backgroundColor !== "transparent" && settings.backgroundColor !== "") {
    simplified.backgroundColor = settings.backgroundColor;
  }

  // Background image and related properties - only if image exists
  if (settings.backgroundImage) {
    simplified.backgroundImage = settings.backgroundImage;
    simplified.backgroundSize = settings.backgroundSize;
    simplified.backgroundPosition = settings.backgroundPosition;
    simplified.backgroundRepeat = settings.backgroundRepeat;
  }

  // Note: We intentionally exclude:
  // - padding/margin (not needed for AI layout generation)
  // - useCustomHtml, customHtml, customCss, customJs (we're generating new ones)
  // - backgroundImageId (not needed for generation)

  return simplified;
}

/**
 * Prepare elements for AI payload
 * Filters visible elements and simplifies their data
 */
export function prepareElementsForAI(elements: CanvasElement[]): SimplifiedElement[] {
  return elements
    .filter((el) => el.visible) // Only include visible elements
    .map(simplifyElement);
}

/**
 * Prepare container settings for AI payload
 */
export function prepareContainerSettingsForAI(settings: ContainerSettings): SimplifiedContainerSettings {
  return simplifyContainerSettings(settings);
}

/**
 * Full payload optimizer - prepares both elements and container settings
 */
export function optimizeAIPayload(elements: CanvasElement[], containerSettings: ContainerSettings) {
  return {
    elements: prepareElementsForAI(elements),
    containerSettings: prepareContainerSettingsForAI(containerSettings),
  };
}
