/**
 * PDF Document Conversion (Shared)
 *
 * Converts PDFDocument schema to pdfmake document definitions.
 * This module is browser-safe and shared between server and browser pdfmake services.
 *
 * @see https://pdfmake.github.io/docs/
 */

import type {
  TDocumentDefinitions,
  Content,
  StyleDictionary,
  ContentText,
  ContentUnorderedList,
  ContentOrderedList,
  ContentTable
} from 'pdfmake/interfaces'

import type { PDFTheme } from '../themes'
import type { ContentBlock, PDFDocument, Page as PDFPage } from '../types'

// ============================================================================
// Style Building
// ============================================================================

/**
 * Build pdfmake styles from theme
 */
export function buildStyles(theme: PDFTheme): StyleDictionary {
  return {
    title: {
      fontSize: theme.typography.title.fontSize,
      bold: theme.typography.title.fontWeight === 'bold',
      color: theme.colors.text,
      lineHeight: 1.1,
      margin: [0, 0, 0, 12] as [number, number, number, number]
    },
    headerSubtitle: {
      fontSize: 12,
      color: theme.colors.textMuted,
      margin: [0, 0, 0, 4] as [number, number, number, number]
    },
    subtitle: {
      fontSize: theme.typography.subtitle.fontSize,
      bold: theme.typography.subtitle.fontWeight === 'bold',
      color: theme.colors.text,
      margin: [0, 12, 0, 0] as [number, number, number, number]
    },
    body: {
      fontSize: theme.typography.body.fontSize,
      lineHeight: 1.2,
      color: theme.colors.textMuted
    },
    caption: {
      fontSize: theme.typography.caption.fontSize,
      color: theme.colors.textMuted // Changed from textSubtle for better visibility
    },
    metric: {
      fontSize: theme.typography.metric.fontSize,
      bold: theme.typography.metric.fontWeight === 'bold',
      color: theme.colors.text,
      lineHeight: 1
    },
    metricLabel: {
      fontSize: 9,
      color: theme.colors.textMuted,
      lineHeight: 1,
      margin: [0, 0, 0, 0] as [number, number, number, number]
    },
    cardTitle: {
      fontSize: theme.typography.subtitle.fontSize,
      bold: true,
      color: theme.colors.text,
      margin: [0, 0, 0, 12] as [number, number, number, number]
    },
    cardTitleDark: {
      fontSize: theme.typography.subtitle.fontSize,
      bold: true,
      color: theme.colors.textDark,
      margin: [0, 0, 0, 12] as [number, number, number, number]
    },
    listItem: {
      fontSize: theme.typography.body.fontSize,
      color: theme.colors.text,
      lineHeight: 1.2,
      margin: [0, 1, 0, 1] as [number, number, number, number]
    },
    listItemHighlight: {
      fontSize: theme.typography.body.fontSize,
      color: '#F5A623',
      bold: false,
      lineHeight: 1.2,
      margin: [0, 1, 0, 1] as [number, number, number, number]
    },
    tableHeader: {
      fontSize: theme.typography.body.fontSize,
      bold: true,
      color: theme.colors.text
    },
    tableCell: {
      fontSize: theme.typography.body.fontSize,
      color: theme.colors.textMuted
    },
    // Cover page styles
    coverCompany: {
      fontSize: 50,
      bold: true,
      color: theme.colors.text,
      lineHeight: 1.1
    },
    coverVertical: {
      fontSize: 24,
      bold: true,
      color: theme.colors.textMuted,
      lineHeight: 1.2,
      margin: [0, 12, 0, 0] as [number, number, number, number]
    },
    coverScope: {
      fontSize: 14,
      color: theme.colors.textMuted,
      margin: [0, 12, 0, 0] as [number, number, number, number]
    },
    coverSolutions: {
      fontSize: 14,
      color: theme.colors.textMuted,
      lineHeight: 1.4,
      margin: [0, 16, 0, 0] as [number, number, number, number]
    }
  }
}

// ============================================================================
// Content Block Conversion
// ============================================================================

/**
 * Convert a content block to pdfmake content
 */
export function convertBlock(block: ContentBlock, theme: PDFTheme): Content {
  switch (block.type) {
    case 'text': {
      const style = block.variant || 'body'
      // Subtitles get negative margin to pull content closer
      const bottomMargin = style === 'subtitle' ? -4 : theme.spacing.section / 2
      return {
        text: block.content,
        style,
        margin: [0, 0, 0, bottomMargin] as [number, number, number, number]
      } as ContentText
    }

    case 'metric': {
      // Stacked metric: value on top, label below, centered
      // Add small top margin to visually balance (font ascenders create extra space above)
      return {
        stack: [
          { text: block.value, style: 'metric', alignment: 'center' } as ContentText,
          { text: block.label, style: 'metricLabel', alignment: 'center' } as ContentText
        ],
        margin: [0, 4, 0, 0] as [number, number, number, number]
      } as Content
    }

    case 'list': {
      const items = block.items.map((item) => {
        if (typeof item === 'string') {
          return { text: item, style: 'listItem' } as ContentText
        }
        return {
          text: item.text,
          style: item.highlight ? 'listItemHighlight' : 'listItem'
        } as ContentText
      })

      if (block.ordered) {
        return {
          ol: items,
          margin: [0, 0, 0, theme.spacing.section / 2] as [number, number, number, number]
        } as ContentOrderedList
      }
      return {
        ul: items,
        markerColor: theme.colors.accent,
        margin: [0, 0, 0, theme.spacing.section / 2] as [number, number, number, number]
      } as ContentUnorderedList
    }

    case 'card': {
      // Card as a bordered box
      const isAccent = block.variant === 'accent'
      const isLight = block.variant === 'light'
      const isHorizontal = block.layout === 'horizontal'
      const cardPadding = 10 // Compact padding

      // Convert nested content
      const convertedContent = block.content.map((nestedBlock) => convertBlock(nestedBlock, theme))

      // Build card inner content
      let innerContent: Content
      if (block.title) {
        const titleStyle = isLight ? 'cardTitleDark' : 'cardTitle'
        const titleContent = { text: block.title, style: titleStyle } as ContentText
        if (isHorizontal) {
          innerContent = {
            stack: [titleContent, { columns: convertedContent, columnGap: 20 }]
          } as Content
        } else {
          innerContent = { stack: [titleContent, ...convertedContent] } as Content
        }
      } else {
        if (isHorizontal) {
          innerContent = { columns: convertedContent, columnGap: 20 } as Content
        } else {
          innerContent = { stack: convertedContent } as Content
        }
      }

      // Determine colors based on variant
      let fillColor: string
      let borderColor: string
      if (isLight) {
        fillColor = theme.colors.cardLightBg
        borderColor = theme.colors.cardLightBorder
      } else if (isAccent) {
        fillColor = theme.colors.cardAccentBg
        borderColor = theme.colors.cardAccentBorder
      } else {
        fillColor = theme.colors.cardBg
        borderColor = theme.colors.cardBorder
      }

      // Use table for card border effect
      return {
        table: {
          widths: ['*'],
          body: [
            [
              {
                stack: [innerContent],
                margin: [cardPadding, cardPadding, cardPadding, cardPadding] as [number, number, number, number]
              }
            ]
          ]
        },
        layout: {
          hLineWidth: () => 1,
          vLineWidth: () => 1,
          hLineColor: () => borderColor,
          vLineColor: () => borderColor,
          fillColor: () => fillColor,
          paddingLeft: () => 0,
          paddingRight: () => 0,
          paddingTop: () => 0,
          paddingBottom: () => 0
        },
        margin: [0, 0, 0, 12] as [number, number, number, number]
      } as ContentTable
    }

    case 'table': {
      // Header row + data rows
      const body = [
        block.headers.map((h) => ({ text: h, style: 'tableHeader' }) as ContentText),
        ...block.rows.map((row) => row.map((cell) => ({ text: cell, style: 'tableCell' }) as ContentText))
      ]

      // Add footer row if provided (styled like header)
      const hasFooter = block.footerRow && block.footerRow.length > 0
      if (hasFooter) {
        body.push(block.footerRow!.map((cell) => ({ text: cell, style: 'tableHeader' }) as ContentText))
      }

      // Use custom column widths if provided, otherwise equal distribution
      const widths = block.columnWidths || block.headers.map(() => '*')

      // Line positions: top, after header, before footer (if exists), bottom
      const lastRowIndex = body.length

      return {
        table: {
          headerRows: 1,
          widths,
          body
        },
        layout: {
          hLineWidth: (i: number, node: { table: { body: unknown[][] } }) => {
            // Lines at: top, below header, above footer (if exists), bottom
            if (i === 0 || i === 1 || i === node.table.body.length) return 1
            if (hasFooter && i === node.table.body.length - 1) return 1
            return 0
          },
          vLineWidth: () => 0,
          hLineColor: () => theme.colors.cardBorder,
          fillColor: (i: number) => {
            // Fill header row and footer row
            if (i === 0) return theme.colors.cardBg
            if (hasFooter && i === lastRowIndex - 1) return theme.colors.cardBg
            return undefined
          },
          // Compact padding for tighter rows
          paddingLeft: () => 8,
          paddingRight: () => 8,
          paddingTop: () => 8,
          paddingBottom: () => 0
        },
        margin: [0, 0, 0, theme.spacing.section] as [number, number, number, number]
      } as ContentTable
    }

    case 'columns': {
      // Simple horizontal layout without card styling (no border, no background)
      const convertedContent = block.content.map((nestedBlock) => convertBlock(nestedBlock, theme))
      return {
        columns: convertedContent,
        columnGap: 20,
        margin: [0, 0, 0, 16] as [number, number, number, number] // Space below metrics
      } as Content
    }
  }
}

// ============================================================================
// Page Conversion
// ============================================================================

/**
 * Convert a page to pdfmake content
 */
export function convertPage(page: PDFPage, pageIndex: number, theme: PDFTheme): Content[] {
  const content: Content[] = []

  // Page break for non-first pages
  if (pageIndex > 0) {
    content.push({ text: '', pageBreak: 'before' } as ContentText)
  }

  // Cover page handling
  if (page.cover) {
    // Top row: logo on left, text on right
    const topLeftContent: Content[] = []
    const topRightContent: Content[] = []

    // Top left - can be logo or content blocks
    if (page.cover.topLeft) {
      // Check if it's a logo object (has 'src' property)
      if ('src' in page.cover.topLeft) {
        const logoSrc = page.cover.topLeft.src
        if (logoSrc.startsWith('data:')) {
          topLeftContent.push({
            image: logoSrc,
            width: page.cover.topLeft.width || 50
          } as Content)
        } else {
          topLeftContent.push({
            text: '[LOGO]',
            style: 'caption'
          } as ContentText)
        }
      } else if (Array.isArray(page.cover.topLeft)) {
        page.cover.topLeft.forEach((block) => {
          topLeftContent.push(convertBlock(block, theme))
        })
      }
    }

    // Top right content
    if (page.cover.topRight) {
      page.cover.topRight.forEach((block) => {
        topRightContent.push(convertBlock(block, theme))
      })
    }

    // Add top row as columns if we have content
    if (topLeftContent.length > 0 || topRightContent.length > 0) {
      content.push({
        columns: [
          { stack: topLeftContent, width: '*' },
          { stack: topRightContent, width: 'auto', alignment: 'right' }
        ],
        margin: [0, 0, 0, 0] as [number, number, number, number]
      } as Content)
    }

    // Main content - centered vertically if centerContent is true
    if (page.cover.centerContent) {
      const mainContent: Content[] = page.sections.map((block) => convertBlock(block, theme))

      content.push({
        stack: mainContent,
        absolutePosition: { x: theme.spacing.page, y: 320 }
      } as Content)
    } else {
      page.sections.forEach((block) => {
        content.push(convertBlock(block, theme))
      })
    }
  } else {
    // Header (for non-cover pages)
    // Add accent line at top left
    content.push({
      canvas: [
        {
          type: 'line',
          x1: 0,
          y1: 0,
          x2: 40,
          y2: 0,
          lineWidth: 3,
          lineColor: theme.colors.accent
        }
      ],
      margin: [0, 0, 0, 12] as [number, number, number, number]
    } as Content)

    if (page.header?.subtitle) {
      content.push({
        text: page.header.subtitle,
        style: 'headerSubtitle'
      } as ContentText)
    }

    if (page.header?.title) {
      content.push({
        text: page.header.title,
        style: 'title',
        margin: [0, 0, 0, 12] as [number, number, number, number]
      } as ContentText)
    }

    // Main content sections
    page.sections.forEach((block) => {
      content.push(convertBlock(block, theme))
    })
  }

  // Cover page bottom content (positioned at bottom)
  if (page.cover) {
    const bottomContent: Content[] = []

    // Build bottom left content
    const leftContent = page.cover.bottomLeft?.map((block) => convertBlock(block, theme)) || []

    // Build bottom right content
    const rightContent = page.cover.bottomRight?.map((block) => convertBlock(block, theme)) || []

    if (leftContent.length > 0 || rightContent.length > 0) {
      bottomContent.push({
        columns: [
          { stack: leftContent, width: '*' },
          { stack: rightContent, width: 'auto', alignment: 'right' }
        ],
        absolutePosition: { x: theme.spacing.page, y: 841.89 - theme.spacing.page - 20 }
      } as Content)
    }

    content.push(...bottomContent)
  }

  return content
}

// ============================================================================
// Document Conversion
// ============================================================================

/**
 * Convert PDFDocument to pdfmake document definition
 */
export function convertDocument(document: PDFDocument, theme: PDFTheme): TDocumentDefinitions {
  // Flatten all pages into content array
  const content: Content[] = []

  document.pages.forEach((page, index) => {
    const pageContent = convertPage(page, index, theme)
    content.push(...pageContent)
  })

  return {
    pageSize: 'A4',
    pageMargins: [theme.spacing.page, theme.spacing.page, theme.spacing.page, theme.spacing.page] as [
      number,
      number,
      number,
      number
    ],
    background: () => ({
      canvas: [
        {
          type: 'rect',
          x: 0,
          y: 0,
          w: 595.28, // A4 width in points
          h: 841.89, // A4 height in points
          color: theme.colors.background
        }
      ]
    }),
    content,
    styles: buildStyles(theme),
    defaultStyle: {
      font: 'Roboto',
      fontSize: theme.typography.body.fontSize,
      color: theme.colors.text,
      lineHeight: theme.typography.body.lineHeight
    },
    info: document.metadata
      ? {
          title: document.metadata.title,
          author: document.metadata.author
        }
      : undefined
  }
}
