/**
 * Responsive CSS Generator Functions for Layout Exporter
 *
 * Generates responsive CSS rules for tablet and mobile breakpoints.
 */

import type { CanvasElement, PriceElement, VariablePriceRangeElement, ContainerSettings, ResponsiveValue } from "@/types";
import { isResponsiveValue } from "@/types";
import type { ContainerBounds } from "../layoutAnalyzer";
import { isPriceElement, isVariablePriceRangeElement, BREAKPOINTS } from "./types";
import { getClassName } from "./utils";

/**
 * Generate responsive typography CSS rules for a specific breakpoint
 */
export function generateResponsiveTypographyRules(el: CanvasElement, breakpoint: "tablet" | "mobile"): string[] {
  const { typography } = el;
  const rules: string[] = [];

  if (typography.fontSize[breakpoint] !== typography.fontSize.desktop) {
    rules.push(`font-size: ${typography.fontSize[breakpoint]}px`);
  }
  if (typography.fontWeight[breakpoint] !== typography.fontWeight.desktop) {
    rules.push(`font-weight: ${typography.fontWeight[breakpoint]}`);
  }
  if (typography.letterSpacing[breakpoint] !== typography.letterSpacing.desktop) {
    rules.push(`letter-spacing: ${typography.letterSpacing[breakpoint]}px`);
  }

  return rules;
}

/**
 * Generate responsive border CSS rules for a specific breakpoint
 */
export function generateResponsiveBorderRules(el: CanvasElement, breakpoint: "tablet" | "mobile"): string[] {
  const { border } = el;
  const rules: string[] = [];

  if (border.width[breakpoint] !== border.width.desktop) {
    if (border.width[breakpoint] > 0) {
      rules.push(`border-width: ${border.width[breakpoint]}px`);
    } else {
      rules.push(`border-width: 0`);
    }
  }

  return rules;
}

/**
 * Generate responsive padding CSS rules for a specific breakpoint
 */
export function generateResponsivePaddingRules(el: CanvasElement, breakpoint: "tablet" | "mobile"): string[] {
  const { padding } = el;
  const rules: string[] = [];

  const topDiff = padding.top[breakpoint] !== padding.top.desktop;
  const rightDiff = padding.right[breakpoint] !== padding.right.desktop;
  const bottomDiff = padding.bottom[breakpoint] !== padding.bottom.desktop;
  const leftDiff = padding.left[breakpoint] !== padding.left.desktop;

  if (topDiff || rightDiff || bottomDiff || leftDiff) {
    rules.push(
      `padding: ${padding.top[breakpoint]}px ${padding.right[breakpoint]}px ${padding.bottom[breakpoint]}px ${padding.left[breakpoint]}px`
    );
  }

  return rules;
}

/**
 * Generate responsive margin CSS rules for a specific breakpoint
 */
export function generateResponsiveMarginRules(el: CanvasElement, breakpoint: "tablet" | "mobile"): string[] {
  const { margin } = el;
  const rules: string[] = [];

  const topDiff = margin.top[breakpoint] !== margin.top.desktop;
  const rightDiff = margin.right[breakpoint] !== margin.right.desktop;
  const bottomDiff = margin.bottom[breakpoint] !== margin.bottom.desktop;
  const leftDiff = margin.left[breakpoint] !== margin.left.desktop;

  if (topDiff || rightDiff || bottomDiff || leftDiff) {
    rules.push(
      `margin: ${margin.top[breakpoint]}px ${margin.right[breakpoint]}px ${margin.bottom[breakpoint]}px ${margin.left[breakpoint]}px`
    );
  }

  return rules;
}

/**
 * Generate responsive decimal CSS rules for price elements
 */
export function generateResponsiveDecimalRules(el: PriceElement, breakpoint: "tablet" | "mobile"): string[] {
  if (!el.decimal?.show || el.decimal.position === "inline") return [];

  const rules: string[] = [];
  const decimalTypo = el.decimal.typography || {};

  const hasExplicitFontSize = decimalTypo.fontSize !== undefined && isResponsiveValue(decimalTypo.fontSize);

  if (hasExplicitFontSize) {
    const fontSize = decimalTypo.fontSize as ResponsiveValue<number>;
    if (fontSize[breakpoint] !== fontSize.desktop) {
      rules.push(`font-size: ${fontSize[breakpoint]}px`);
    }
  } else {
    const mainFontSize = el.typography.fontSize;
    const desktopDecimalSize = Math.round(mainFontSize.desktop * 0.6);
    const breakpointDecimalSize = Math.round(mainFontSize[breakpoint] * 0.6);

    if (breakpointDecimalSize !== desktopDecimalSize) {
      rules.push(`font-size: ${breakpointDecimalSize}px`);
    }
  }

  if (decimalTypo.fontWeight && isResponsiveValue(decimalTypo.fontWeight)) {
    const fontWeight = decimalTypo.fontWeight as ResponsiveValue<number>;
    if (fontWeight[breakpoint] !== fontWeight.desktop) {
      rules.push(`font-weight: ${fontWeight[breakpoint]}`);
    }
  }

  if (decimalTypo.letterSpacing && isResponsiveValue(decimalTypo.letterSpacing)) {
    const letterSpacing = decimalTypo.letterSpacing as ResponsiveValue<number>;
    if (letterSpacing[breakpoint] !== letterSpacing.desktop) {
      rules.push(`letter-spacing: ${letterSpacing[breakpoint]}px`);
    }
  }

  return rules;
}

/**
 * Generate responsive CSS rules for variable price range element
 */
export function generateResponsiveVariableRangeRules(
  el: VariablePriceRangeElement,
  breakpoint: "tablet" | "mobile"
): Map<string, string[]> {
  const className = "oppb-variable-range";
  const result = new Map<string, string[]>();

  const mainFontSize = el.typography.fontSize;

  const valuesDiffer = (value: ResponsiveValue<number> | undefined, bp: "tablet" | "mobile"): boolean => {
    if (!value) return false;
    return value[bp] !== value.desktop;
  };

  const getBpValue = (value: ResponsiveValue<number> | undefined, fallback: number): number => {
    if (!value) return fallback;
    return value[breakpoint];
  };

  // Separator responsive rules
  const hasSeparatorFontSize = el.separatorTypography?.fontSize !== undefined;
  if (hasSeparatorFontSize && valuesDiffer(el.separatorTypography!.fontSize, breakpoint)) {
    const sepFontSize = getBpValue(el.separatorTypography!.fontSize, mainFontSize[breakpoint] * 0.75);
    result.set(`.${className}__separator`, [`font-size: ${sepFontSize}px`]);
    result.set(`.${className}__prefix`, [`font-size: ${sepFontSize}px`]);
  } else if (valuesDiffer(mainFontSize, breakpoint)) {
    const sepFontSize = Math.round(mainFontSize[breakpoint] * 0.75);
    result.set(`.${className}__separator`, [`font-size: ${sepFontSize}px`]);
    result.set(`.${className}__prefix`, [`font-size: ${sepFontSize}px`]);
  }

  // Min price responsive rules
  const hasMinFontSize = el.minPriceTypography?.fontSize !== undefined;
  const minRules: string[] = [];
  if (hasMinFontSize && valuesDiffer(el.minPriceTypography!.fontSize, breakpoint)) {
    const minFontSizeValue = getBpValue(el.minPriceTypography!.fontSize, mainFontSize[breakpoint]);
    minRules.push(`font-size: ${minFontSizeValue}px`);
  } else if (valuesDiffer(mainFontSize, breakpoint)) {
    minRules.push(`font-size: ${mainFontSize[breakpoint]}px`);
  }
  if (minRules.length > 0) {
    result.set(`.${className}__min`, minRules);
  }

  // Max price responsive rules
  const hasMaxFontSize = el.maxPriceTypography?.fontSize !== undefined;
  const maxRules: string[] = [];
  if (hasMaxFontSize && valuesDiffer(el.maxPriceTypography!.fontSize, breakpoint)) {
    const maxFontSizeValue = getBpValue(el.maxPriceTypography!.fontSize, mainFontSize[breakpoint]);
    maxRules.push(`font-size: ${maxFontSizeValue}px`);
  } else if (valuesDiffer(mainFontSize, breakpoint)) {
    maxRules.push(`font-size: ${mainFontSize[breakpoint]}px`);
  }
  if (maxRules.length > 0) {
    result.set(`.${className}__max`, maxRules);
  }

  // Min decimal responsive rules
  if (el.minDecimal?.show && el.minDecimal.position !== "inline") {
    const decTypo = el.minDecimal.typography || {};
    const minDecRules: string[] = [];

    const hasExplicitFontSize = decTypo.fontSize !== undefined && isResponsiveValue(decTypo.fontSize);

    if (hasExplicitFontSize) {
      const fontSize = decTypo.fontSize as ResponsiveValue<number>;
      if (fontSize[breakpoint] !== fontSize.desktop) {
        minDecRules.push(`font-size: ${fontSize[breakpoint]}px`);
      }
    } else {
      const minFontSizeVal = hasMinFontSize ? el.minPriceTypography!.fontSize : mainFontSize;
      if (minFontSizeVal && isResponsiveValue(minFontSizeVal)) {
        const desktopDecimalSize = Math.round(minFontSizeVal.desktop * 0.6);
        const breakpointDecimalSize = Math.round(minFontSizeVal[breakpoint] * 0.6);
        if (breakpointDecimalSize !== desktopDecimalSize) {
          minDecRules.push(`font-size: ${breakpointDecimalSize}px`);
        }
      }
    }

    if (minDecRules.length > 0) {
      result.set(`.${className}__min-decimal`, minDecRules);
    }
  }

  // Max decimal responsive rules
  if (el.maxDecimal?.show && el.maxDecimal.position !== "inline") {
    const decTypo = el.maxDecimal.typography || {};
    const maxDecRules: string[] = [];

    const hasExplicitFontSize = decTypo.fontSize !== undefined && isResponsiveValue(decTypo.fontSize);

    if (hasExplicitFontSize) {
      const fontSize = decTypo.fontSize as ResponsiveValue<number>;
      if (fontSize[breakpoint] !== fontSize.desktop) {
        maxDecRules.push(`font-size: ${fontSize[breakpoint]}px`);
      }
    } else {
      const maxFontSizeVal = hasMaxFontSize ? el.maxPriceTypography!.fontSize : mainFontSize;
      if (maxFontSizeVal && isResponsiveValue(maxFontSizeVal)) {
        const desktopDecimalSize = Math.round(maxFontSizeVal.desktop * 0.6);
        const breakpointDecimalSize = Math.round(maxFontSizeVal[breakpoint] * 0.6);
        if (breakpointDecimalSize !== desktopDecimalSize) {
          maxDecRules.push(`font-size: ${breakpointDecimalSize}px`);
        }
      }
    }

    if (maxDecRules.length > 0) {
      result.set(`.${className}__max-decimal`, maxDecRules);
    }
  }

  return result;
}

/**
 * Generate responsive container spacing rules
 */
export function generateResponsiveContainerRules(
  containerSettings: ContainerSettings,
  breakpoint: "tablet" | "mobile",
  containerBounds?: ContainerBounds
): string[] {
  const { padding, margin, border } = containerSettings;
  const rules: string[] = [];

  // Check padding differences
  const paddingTopDiff = padding.top[breakpoint] !== padding.top.desktop;
  const paddingRightDiff = padding.right[breakpoint] !== padding.right.desktop;
  const paddingBottomDiff = padding.bottom[breakpoint] !== padding.bottom.desktop;
  const paddingLeftDiff = padding.left[breakpoint] !== padding.left.desktop;

  if (paddingTopDiff || paddingRightDiff || paddingBottomDiff || paddingLeftDiff) {
    rules.push(
      `padding: ${padding.top[breakpoint]}px ${padding.right[breakpoint]}px ${padding.bottom[breakpoint]}px ${padding.left[breakpoint]}px`
    );

    if (containerBounds) {
      const desktopPaddingH = padding.left.desktop + padding.right.desktop;
      const desktopPaddingV = padding.top.desktop + padding.bottom.desktop;
      const breakpointPaddingH = padding.left[breakpoint] + padding.right[breakpoint];
      const breakpointPaddingV = padding.top[breakpoint] + padding.bottom[breakpoint];

      const contentWidth = containerBounds.width - desktopPaddingH;
      const contentHeight = containerBounds.height - desktopPaddingV;

      const newMinWidth = Math.round(contentWidth + breakpointPaddingH);
      const newMinHeight = Math.round(contentHeight + breakpointPaddingV);

      rules.push(`--oppb-min-width: ${newMinWidth}px`);
      rules.push(`--oppb-min-height: ${newMinHeight}px`);
    }
  }

  // Check margin differences
  const marginTopDiff = margin.top[breakpoint] !== margin.top.desktop;
  const marginRightDiff = margin.right[breakpoint] !== margin.right.desktop;
  const marginBottomDiff = margin.bottom[breakpoint] !== margin.bottom.desktop;
  const marginLeftDiff = margin.left[breakpoint] !== margin.left.desktop;

  if (marginTopDiff || marginRightDiff || marginBottomDiff || marginLeftDiff) {
    rules.push(
      `margin: ${margin.top[breakpoint]}px ${margin.right[breakpoint]}px ${margin.bottom[breakpoint]}px ${margin.left[breakpoint]}px`
    );
  }

  // Check border width differences
  if (border.width[breakpoint] !== border.width.desktop) {
    if (border.width[breakpoint] > 0) {
      rules.push(`border-width: ${border.width[breakpoint]}px`);
    } else {
      rules.push(`border-width: 0`);
    }
  }

  return rules;
}

/**
 * Collect all responsive rules for an element
 */
export function collectElementResponsiveRules(el: CanvasElement, breakpoint: "tablet" | "mobile"): string[] {
  const rules: string[] = [];

  rules.push(...generateResponsiveTypographyRules(el, breakpoint));
  rules.push(...generateResponsiveBorderRules(el, breakpoint));
  rules.push(...generateResponsivePaddingRules(el, breakpoint));
  rules.push(...generateResponsiveMarginRules(el, breakpoint));

  return rules;
}

/**
 * Generate media query CSS block
 */
export function generateMediaQueryCSS(tabletRules: Map<string, string[]>, mobileRules: Map<string, string[]>): string {
  const mediaQueries: string[] = [];

  // Tablet media query
  if (tabletRules.size > 0) {
    const tabletCSS: string[] = [];
    tabletRules.forEach((rules, selector) => {
      if (rules.length > 0) {
        tabletCSS.push(`  ${selector} {\n    ${rules.join(";\n    ")};\n  }`);
      }
    });

    if (tabletCSS.length > 0) {
      mediaQueries.push("");
      mediaQueries.push(`/* Tablet styles */`);
      mediaQueries.push(`@media (max-width: ${BREAKPOINTS.tablet}px) {`);
      mediaQueries.push(tabletCSS.join("\n\n"));
      mediaQueries.push(`}`);
    }
  }

  // Mobile media query
  if (mobileRules.size > 0) {
    const mobileCSS: string[] = [];
    mobileRules.forEach((rules, selector) => {
      if (rules.length > 0) {
        mobileCSS.push(`  ${selector} {\n    ${rules.join(";\n    ")};\n  }`);
      }
    });

    if (mobileCSS.length > 0) {
      mediaQueries.push("");
      mediaQueries.push(`/* Mobile styles */`);
      mediaQueries.push(`@media (max-width: ${BREAKPOINTS.mobile}px) {`);
      mediaQueries.push(mobileCSS.join("\n\n"));
      mediaQueries.push(`}`);
    }
  }

  return mediaQueries.join("\n");
}

/**
 * Collect all responsive rules for visible elements
 */
export function collectAllResponsiveRules(visibleElements: CanvasElement[], breakpoint: "tablet" | "mobile"): Map<string, string[]> {
  const rules = new Map<string, string[]>();

  visibleElements.forEach((el) => {
    const className = getClassName(el.type);
    const elRules = collectElementResponsiveRules(el, breakpoint);
    if (elRules.length > 0) {
      rules.set(`.${className}`, elRules);
    }

    // Handle price decimal responsive rules
    if (isPriceElement(el)) {
      const decimalRules = generateResponsiveDecimalRules(el, breakpoint);
      if (decimalRules.length > 0) {
        rules.set(`.${className}__decimal`, decimalRules);
      }
    }

    // Handle variable price range responsive rules
    if (isVariablePriceRangeElement(el)) {
      const rangeRules = generateResponsiveVariableRangeRules(el, breakpoint);
      rangeRules.forEach((r, selector) => {
        rules.set(selector, r);
      });
    }
  });

  return rules;
}
