import { StyleOption, ElementStyle, FontConfig, ColorPalette } from '../types';

/**
 * Resolves a color reference (e.g., 'accent', 'background') or returns the color directly
 */
export function resolveColor(color: string | undefined, palette: ColorPalette): string {
  if (!color) return '#000000';
  // Check if it's a palette reference
  if (palette[color as keyof ColorPalette]) {
    return '#' + palette[color as keyof ColorPalette];
  }
  // Return as-is with # prefix if not already present
  return color.startsWith('#') ? color : '#' + color;
}

/**
 * Resolves a font reference (e.g., 'heading', 'body', 'code') to actual font name
 */
export function resolveFont(font: string | undefined, fonts: FontConfig): string {
  if (!font) return 'serif';
  // Check if it's a font reference
  if (fonts[font as keyof FontConfig]) {
    return fonts[font as keyof FontConfig]!;
  }
  // Return as-is (already an actual font name)
  return font;
}

/**
 * Converts element style to CSS string
 */
function elementToCss(
  selector: string,
  style: ElementStyle | undefined,
  fonts: FontConfig,
  palette: ColorPalette
): string {
  if (!style) return '';

  const css: string[] = [];

  if (style.font) css.push(`font-family: ${resolveFont(style.font, fonts)}`);
  if (style.size) css.push(`font-size: ${style.size}pt`);
  if (style.color) css.push(`color: ${resolveColor(style.color, palette)}`);
  if (style.background) css.push(`background: ${resolveColor(style.background, palette)}`);
  if (style.bold) css.push('font-weight: 700');
  if (style.italic) css.push('font-style: italic');
  if (style.underline) css.push('text-decoration: underline');
  if (style.allCaps) css.push('text-transform: uppercase');
  if (style.align) css.push(`text-align: ${style.align === 'both' ? 'justify' : style.align}`);
  if (style.spacing) {
    if (style.spacing.before) css.push(`margin-top: ${style.spacing.before}pt`);
    if (style.spacing.after) css.push(`margin-bottom: ${style.spacing.after}pt`);
    if (style.spacing.line) css.push(`line-height: ${style.spacing.line}`);
  }
  if (style.indent) css.push(`text-indent: ${style.indent}pt`);
  if (style.padding) css.push(`padding: ${style.padding}pt`);
  if (style.border) {
    css.push(`border: ${style.border.width}px ${style.border.style} ${resolveColor(style.border.color, palette)}`);
  }
  if (style.borderTop) {
    css.push(`border-top: ${style.borderTop.width}px ${style.borderTop.style} ${resolveColor(style.borderTop.color, palette)}`);
  }
  if (style.borderBottom) {
    css.push(`border-bottom: ${style.borderBottom.width}px ${style.borderBottom.style} ${resolveColor(style.borderBottom.color, palette)}`);
  }
  if (style.borderLeft) {
    css.push(`border-left: ${style.borderLeft.width}px ${style.borderLeft.style} ${resolveColor(style.borderLeft.color, palette)}`);
  }
  if (style.borderRight) {
    css.push(`border-right: ${style.borderRight.width}px ${style.borderRight.style} ${resolveColor(style.borderRight.color, palette)}`);
  }

  if (css.length === 0) return '';
  return `${selector} { ${css.join('; ')} }`;
}

/**
 * Generates preview CSS from unified template structure
 * This is the SINGLE SOURCE OF TRUTH for both preview and export styling
 * All selectors are scoped to .page to avoid affecting the app background
 */
export function generatePreviewCss(template: StyleOption): string {
  const fonts = template.typography?.fonts || { heading: 'serif', body: 'serif', code: 'monospace' };
  const palette = template.typography?.colors || { text: '000000', background: 'FFFFFF' };
  const elements = template.elements || {};

  const cssParts: string[] = [];

  // .page base styles - scoped to avoid affecting app background
  const baseStyles: string[] = [];
  baseStyles.push(`font-family: ${resolveFont('body', fonts)}`);
  baseStyles.push(`background: ${resolveColor('background', palette)}`);
  baseStyles.push(`color: ${resolveColor('text', palette)}`);
  baseStyles.push(`line-height: 1.5`);
  cssParts.push(`.page { ${baseStyles.join('; ')}; min-height: 100%; }`);
  cssParts.push(`.page blockquote, .page table, .page img { break-inside: avoid; }`);

  // Headings - scoped to .page
  cssParts.push(elementToCss('.page h1', elements.h1, fonts, palette));
  cssParts.push(elementToCss('.page h2', elements.h2, fonts, palette));
  cssParts.push(elementToCss('.page h3', elements.h3, fonts, palette));
  cssParts.push(elementToCss('.page h4', elements.h4, fonts, palette));
  cssParts.push(elementToCss('.page h5', elements.h5, fonts, palette));
  cssParts.push(elementToCss('.page h6', elements.h6, fonts, palette));

  // Paragraph - scoped to .page
  cssParts.push(elementToCss('.page p', elements.p, fonts, palette));

  // Blockquote - scoped to .page
  cssParts.push(elementToCss('.page blockquote', elements.blockquote, fonts, palette));

  // Code - scoped to .page
  cssParts.push(elementToCss('.page code', elements.code, fonts, palette));
  cssParts.push(elementToCss('.page pre', elements.pre, fonts, palette));
  cssParts.push('.page pre code { background: transparent !important; padding: 0 !important }');

  // Lists - scoped to .page
  cssParts.push(elementToCss('.page ul', elements.ul, fonts, palette));
  cssParts.push(elementToCss('.page ol', elements.ol, fonts, palette));
  cssParts.push(elementToCss('.page li', elements.li, fonts, palette));

  // Inline styles - scoped to .page
  cssParts.push(elementToCss('.page strong', elements.strong, fonts, palette));
  cssParts.push(elementToCss('.page em', elements.em, fonts, palette));
  cssParts.push(elementToCss('.page a', elements.a, fonts, palette));

  // Tables - scoped to .page
  cssParts.push('.page table { border-collapse: collapse; border-spacing: 0; width: 100%; }');
  cssParts.push(elementToCss('.page table', elements.table, fonts, palette));
  cssParts.push(elementToCss('.page th', elements.th, fonts, palette));
  cssParts.push(elementToCss('.page td', elements.td, fonts, palette));

  // Horizontal rule - scoped to .page
  if (elements.hr?.border) {
    const borderColor = resolveColor(elements.hr.border.color, palette);
    cssParts.push(`.page hr { border: none; border-top: ${elements.hr.border.width}px ${elements.hr.border.style} ${borderColor}; margin: ${elements.hr.spacing?.before || 12}pt 0 }`);
  }

  // Images - scoped to .page
  if (elements.img?.align) {
    cssParts.push(`.page img { display: block; text-align: ${elements.img.align}; margin: ${elements.img.spacing?.before || 12}pt auto }`);
  }

  // Remove empty rules and join
  return cssParts.filter(part => part.trim()).join('\n');
}

/**
 * Generates CSS from legacy wordConfig structure
 * Used when unified elements/typography structure isn't available
 * All selectors are scoped to .page to avoid affecting the app background
 */
function generateCssFromWordConfig(template: StyleOption): string {
  const cfg = template.wordConfig;
  if (!cfg) return '.page { font-family: serif; }';

  const cssParts: string[] = [];

  // .page base styles - scoped to avoid affecting app background
  const pageStyles: string[] = [];
  if (cfg.body?.font) pageStyles.push(`font-family: ${cfg.body.font}`);
  if (cfg.body?.size) pageStyles.push(`font-size: ${cfg.body.size}pt`);
  if (cfg.body?.color) pageStyles.push(`color: #${cfg.body.color}`);
  if (cfg.body?.align) pageStyles.push(`text-align: ${cfg.body.align === 'both' ? 'justify' : cfg.body.align}`);
  if (cfg.body?.spacing?.line) {
    pageStyles.push(`line-height: ${cfg.body.spacing.line / 240}`);
  }
  // White background for the document page
  pageStyles.push('background: #ffffff');
  cssParts.push(`.page { ${pageStyles.join('; ')} }`);

  // Headings - scoped to .page
  if (cfg.heading1) {
    const h1Styles: string[] = [];
    if (cfg.heading1.font) h1Styles.push(`font-family: ${cfg.heading1.font}`);
    if (cfg.heading1.size) h1Styles.push(`font-size: ${cfg.heading1.size}pt`);
    if (cfg.heading1.color) h1Styles.push(`color: #${cfg.heading1.color}`);
    if (cfg.heading1.bold) h1Styles.push('font-weight: 700');
    if (cfg.heading1.italic) h1Styles.push('font-style: italic');
    if (cfg.heading1.allCaps) h1Styles.push('text-transform: uppercase');
    if (cfg.heading1.align) h1Styles.push(`text-align: ${cfg.heading1.align}`);
    if (cfg.heading1.spacing?.before) {
      h1Styles.push(`margin-top: ${cfg.heading1.spacing.before / 20}pt`);
    }
    if (cfg.heading1.spacing?.after) {
      h1Styles.push(`margin-bottom: ${cfg.heading1.spacing.after / 20}pt`);
    }
    cssParts.push(`.page h1 { ${h1Styles.join('; ')} }`);
  }

  if (cfg.heading2) {
    const h2Styles: string[] = [];
    if (cfg.heading2.font) h2Styles.push(`font-family: ${cfg.heading2.font}`);
    if (cfg.heading2.size) h2Styles.push(`font-size: ${cfg.heading2.size}pt`);
    if (cfg.heading2.color) h2Styles.push(`color: #${cfg.heading2.color}`);
    if (cfg.heading2.bold) h2Styles.push('font-weight: 700');
    if (cfg.heading2.italic) h2Styles.push('font-style: italic');
    if (cfg.heading2.allCaps) h2Styles.push('text-transform: uppercase');
    if (cfg.heading2.align) h2Styles.push(`text-align: ${cfg.heading2.align}`);
    if (cfg.heading2.spacing?.before) {
      h2Styles.push(`margin-top: ${cfg.heading2.spacing.before / 20}pt`);
    }
    if (cfg.heading2.spacing?.after) {
      h2Styles.push(`margin-bottom: ${cfg.heading2.spacing.after / 20}pt`);
    }
    cssParts.push(`.page h2 { ${h2Styles.join('; ')} }`);
  }

  // Paragraph - scoped to .page
  if (cfg.body) {
    const pStyles: string[] = [];
    if (cfg.body.font) pStyles.push(`font-family: ${cfg.body.font}`);
    if (cfg.body.size) pStyles.push(`font-size: ${cfg.body.size}pt`);
    if (cfg.body.color) pStyles.push(`color: #${cfg.body.color}`);
    if (cfg.body.align) pStyles.push(`text-align: ${cfg.body.align === 'both' ? 'justify' : cfg.body.align}`);
    if (cfg.body.spacing?.line) {
      pStyles.push(`line-height: ${cfg.body.spacing.line / 240}`);
    }
    if (cfg.body.spacing?.after) {
      pStyles.push(`margin-bottom: ${cfg.body.spacing.after / 20}pt`);
    }
    cssParts.push(`.page p { ${pStyles.join('; ')} }`);
  }

  // All other elements scoped to .page
  cssParts.push('.page blockquote { border-left: 3px solid #' + (cfg.accentColor || 'cccccc') + '; padding-left: 16px; margin: 16px 0; font-style: italic; }');
  cssParts.push('.page ul, .page ol { margin: 16px 0; padding-left: 32px; }');
  cssParts.push('.page li { margin-bottom: 8px; }');
  cssParts.push('.page strong { font-weight: 700; }');
  cssParts.push('.page em { font-style: italic; }');
  cssParts.push('.page code { font-family: monospace; background: #f5f5f5; padding: 2px 4px; border-radius: 3px; }');
  cssParts.push('.page pre { background: #f5f5f5; padding: 16px; border-radius: 4px; overflow-x: auto; }');
  cssParts.push('.page table { border-collapse: collapse; width: 100%; margin: 16px 0; }');
  cssParts.push('.page th, .page td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; }');
  cssParts.push('.page th { background: #f5f5f5; font-weight: 700; }');
  cssParts.push('.page hr { border: none; border-top: 1px solid #' + (cfg.accentColor || 'cccccc') + '; margin: 24px 0; }');

  return cssParts.join('\n');
}

/**
 * Gets complete CSS for preview
 * Always generates fresh CSS from unified template structure
 */
export function getPreviewCss(template: StyleOption): string {
  // Always generate CSS from unified structure if available
  if (template.elements && template.typography) {
    return generatePreviewCss(template);
  }
  // Generate CSS from legacy wordConfig structure
  if (template.wordConfig) {
    return generateCssFromWordConfig(template);
  }
  // Final fallback
  return 'body { font-family: serif; color: #000000; background: #ffffff; }';
}

/**
 * Generates Word-compatible wordConfig from unified template structure
 */
// Export this function to be used by templateLoader
export function generateWordConfig(
  elements: Record<string, ElementStyle>,
  fonts: FontConfig,
  palette: ColorPalette
) {
  const h1 = elements.h1;
  const h2 = elements.h2;
  const body = elements.p;

  const toTwips = (pts?: number) => pts;
  const toLineTwips = (line?: number) => line;

  // Helper to ensure borders are preserved in the config
  const mapBorder = (el?: ElementStyle, side?: 'top' | 'bottom' | 'left' | 'right') => {
    // If specific side border exists
    let sideBorder;
    if (side === 'left') sideBorder = el?.borderLeft;
    else if (side === 'top') sideBorder = el?.borderTop;
    else if (side === 'bottom') sideBorder = el?.borderBottom;
    else if (side === 'right') sideBorder = el?.borderRight;

    if (sideBorder) {
      return {
        color: resolveColor(sideBorder.color, palette).replace('#', ''),
        space: 24, // Standard space
        style: sideBorder.style || 'single',
        size: (sideBorder.width || 1) * 8
      };
    }

    // If global border exists
    if (el?.border) {
      return {
        color: resolveColor(el.border.color, palette).replace('#', ''),
        space: 24, // Standard space
        style: el.border.style || 'single',
        size: (el.border.width || 1) * 8
      };
    }

    return undefined;
  };

  return {
    heading1: h1 ? {
      font: resolveFont(h1.font, fonts),
      size: h1.size || 24,
      color: h1.color ? resolveColor(h1.color, palette).replace('#', '') : '000000',
      bold: h1.bold,
      italic: h1.italic,
      allCaps: h1.allCaps,
      align: h1.align,
      spacing: h1.spacing ? {
        before: toTwips(h1.spacing.before) || 0,
        after: toTwips(h1.spacing.after) || 0,
        line: toLineTwips(h1.spacing.line) || 240
      } : undefined,
      // Map borders specifically for H1 if they exist
      border: {
        left: mapBorder(h1, 'left'),
        bottom: mapBorder(h1, 'bottom'),
        top: mapBorder(h1, 'top'),
        right: mapBorder(h1, 'right')
      },
      shading: h1.background ? {
        fill: resolveColor(h1.background, palette).replace('#', ''),
        type: 'clear', // Always use clear for shading to avoid black blocks
        color: 'auto'
      } : undefined
    } : undefined,
    heading2: h2 ? {
      font: resolveFont(h2.font, fonts),
      size: h2.size || 18,
      color: h2.color ? resolveColor(h2.color, palette).replace('#', '') : '333333',
      bold: h2.bold,
      italic: h2.italic,
      allCaps: h2.allCaps,
      align: h2.align,
      spacing: h2.spacing ? {
        before: toTwips(h2.spacing.before) || 0,
        after: toTwips(h2.spacing.after) || 0,
        line: toLineTwips(h2.spacing.line) || 240
      } : undefined,
      shading: h2.background ? {
        fill: resolveColor(h2.background, palette).replace('#', ''),
        type: 'clear',
        color: 'auto'
      } : undefined
    } : undefined,
    body: body ? {
      font: resolveFont(body.font, fonts),
      size: body.size || 11,
      color: body.color ? resolveColor(body.color, palette).replace('#', '') : '000000',
      align: body.align,
      spacing: body.spacing ? {
        before: toTwips(body.spacing.before) || 0,
        after: toTwips(body.spacing.after) || 0,
        line: toLineTwips(body.spacing.line) || 1.2
      } : undefined
    } : undefined,
    accentColor: palette.accent || '000000',
    heading3: elements.h3 ? {
      font: resolveFont(elements.h3.font, fonts),
      size: elements.h3.size || 14,
      color: elements.h3.color ? resolveColor(elements.h3.color, palette).replace('#', '') : '111111',
      bold: elements.h3.bold,
      italic: elements.h3.italic,
      allCaps: elements.h3.allCaps,
      align: elements.h3.align,
      spacing: elements.h3.spacing ? {
        before: toTwips(elements.h3.spacing.before) || 0,
        after: toTwips(elements.h3.spacing.after) || 0,
        line: toLineTwips(elements.h3.spacing.line) || 240
      } : undefined
    } : undefined,
    heading4: elements.h4 ? {
      font: resolveFont(elements.h4.font, fonts),
      size: elements.h4.size || 12,
      color: elements.h4.color ? resolveColor(elements.h4.color, palette).replace('#', '') : '111111',
      bold: elements.h4.bold,
      italic: elements.h4.italic,
      align: elements.h4.align,
      spacing: elements.h4.spacing ? {
        before: toTwips(elements.h4.spacing.before) || 0,
        after: toTwips(elements.h4.spacing.after) || 0,
        line: toLineTwips(elements.h4.spacing.line) || 240
      } : undefined
    } : undefined,
    heading5: elements.h5 ? {
      font: resolveFont(elements.h5.font, fonts),
      size: elements.h5.size || 11,
      color: elements.h5.color ? resolveColor(elements.h5.color, palette).replace('#', '') : '111111',
      bold: elements.h5.bold,
      italic: elements.h5.italic,
      align: elements.h5.align,
      spacing: elements.h5.spacing ? {
        before: toTwips(elements.h5.spacing.before) || 0,
        after: toTwips(elements.h5.spacing.after) || 0,
        line: toLineTwips(elements.h5.spacing.line) || 240
      } : undefined
    } : undefined,
    heading6: elements.h6 ? {
      font: resolveFont(elements.h6.font, fonts),
      size: elements.h6.size || 10,
      color: elements.h6.color ? resolveColor(elements.h6.color, palette).replace('#', '') : '111111',
      bold: elements.h6.bold,
      italic: elements.h6.italic,
      align: elements.h6.align,
      spacing: elements.h6.spacing ? {
        before: toTwips(elements.h6.spacing.before) || 0,
        after: toTwips(elements.h6.spacing.after) || 0,
        line: toLineTwips(elements.h6.spacing.line) || 240
      } : undefined
    } : undefined
  };
}

/**
 * Gets complete wordConfig, preferring generated config over legacy
 */
export function getWordConfig(template: StyleOption) {
  // If template has unified structure, generate config from it
  if (template.elements && template.typography) {
    const fonts = template.typography.fonts || {};
    const palette = template.typography.colors || {};
    const elements = template.elements;
    return generateWordConfig(elements, fonts, palette);
  }
  // Fall back to legacy wordConfig
  return template.wordConfig;
}
