/**
 * Content Plan Mapper
 * Maps parsed content plan blocks to Pug block structures for the email builder.
 */

import { createId } from './utils.js'

/**
 * Find a block template by name pattern from block.pug parsed blocks
 * @param {Array} allBlocks - [{name, content}] from block.pug
 * @param {RegExp|string} pattern - name to match
 */
function findBlock(allBlocks, pattern) {
  const re = pattern instanceof RegExp ? pattern : new RegExp(pattern, 'i')
  return allBlocks.find(b => re.test(b.name))
}

/**
 * Get product mixin name for N products from settings
 */
function getProductMixin(settings, count) {
  const rules = settings?.mixinRules || []
  const productMixins = [...new Set(rules.filter(r => r.type === 'mixin-ids').map(r => r.mixin))]
  if (!productMixins.length) {
    // Fallback: guess from common naming
    if (count >= 3) return 'products3inRow'
    if (count === 2) return 'products2inRow'
    return 'products1Row'
  }
  // Find mixin matching slot count
  const getMixinSlots = (name) => {
    const m = name.match(/(\d)/)
    return m ? parseInt(m[1]) : 1
  }
  // Exact match first
  for (const m of productMixins) {
    if (getMixinSlots(m) === count) return m
  }
  // Closest match
  const sorted = productMixins.sort((a, b) => Math.abs(getMixinSlots(a) - count) - Math.abs(getMixinSlots(b) - count))
  return sorted[0] || 'products1Row'
}

/**
 * Replace first text field content in a pug block template
 */
function injectText(template, newText) {
  // Find the text part after the last pug tag: "span.text Something" → replace "Something"
  const lines = template.split('\n')
  for (let i = lines.length - 1; i >= 0; i--) {
    const line = lines[i]
    // Match lines with span/td/p that have text content
    const match = line.match(/^(\s*(?:span|td|p|div)\S*\s+)(.+)$/)
    if (match && !match[2].startsWith('+') && !match[2].startsWith('//') && !match[2].startsWith('|')) {
      lines[i] = match[1] + newText
      return lines.join('\n')
    }
    // Match pipe text: "| Some text"
    const pipeMatch = line.match(/^(\s*\|\s*)(.+)$/)
    if (pipeMatch) {
      lines[i] = pipeMatch[1] + newText
      return lines.join('\n')
    }
  }
  // Fallback: just return template
  return template
}

/**
 * Replace mixin text arg (first quoted arg)
 */
function injectMixinText(template, newText) {
  return template.replace(/(["'])([^"']*)\1/, `"${newText.replace(/"/g, '\\"')}"`)
}

/**
 * Map parsed blocks to assembled block format
 * @param {Array} parsedBlocks - [{type, content?, ids?, text?}]
 * @param {Array} allBlocks - [{name, content}] from block.pug
 * @param {Object} settings - project settings
 * @returns {Array} - assembled blocks ready for draft
 */
export function mapParsedBlocksToAssembled(parsedBlocks, allBlocks, settings) {
  const result = []

  for (const parsed of parsedBlocks) {
    let block = null

    switch (parsed.type) {
      case 'banner': {
        const tmpl = findBlock(allBlocks, /^Баннер/)
        if (tmpl) {
          block = {
            id: createId(),
            name: tmpl.name,
            content: tmpl.content,
            collapsed: true,
            addSpacing: true,
          }
        }
        break
      }

      case 'heading': {
        const tmpl = findBlock(allBlocks, /^Заголовок/)
        if (tmpl && parsed.content) {
          block = {
            id: createId(),
            name: tmpl.name,
            content: injectText(tmpl.content, parsed.content),
            collapsed: false,
            addSpacing: true,
          }
        }
        break
      }

      case 'text': {
        const tmpl = findBlock(allBlocks, /^Текст/)
        if (tmpl && parsed.content) {
          block = {
            id: createId(),
            name: tmpl.name,
            content: injectText(tmpl.content, parsed.content),
            collapsed: false,
            addSpacing: true,
          }
        }
        break
      }

      case 'products': {
        if (parsed.ids && parsed.ids.length > 0) {
          const mixin = getProductMixin(settings, parsed.ids.length)
          const content = `+${mixin}("${parsed.ids.join(',')}")`
          block = {
            id: createId(),
            name: mixin,
            content,
            collapsed: false,
            addSpacing: true,
          }
        }
        break
      }

      case 'button': {
        const tmpl = findBlock(allBlocks, /^Кнопка/)
        if (tmpl && parsed.text) {
          block = {
            id: createId(),
            name: tmpl.name,
            content: injectMixinText(tmpl.content, parsed.text),
            collapsed: false,
            addSpacing: true,
          }
        }
        break
      }
    }

    if (block) result.push(block)
  }

  return result
}
