export function cleanUpSvgCode(svgCode: string): string {
  return svgCode.replaceAll('<br>', '<br/>')
}

/**
 * Preprocesses mermaid code to fix common syntax issues
 */
export function preprocessMermaidCode(code: string): string {
  if (!code || typeof code !== 'string')
    return ''

  // First check if this is a gantt chart
  if (code.trim().startsWith('gantt')) {
    // For gantt charts, we need to ensure each task is on its own line
    // Split the code into lines and process each line separately
    const lines = code.split('\n').map(line => line.trim())
    return lines.join('\n')
  }

  return code
    // Replace English colons with Chinese colons in section nodes to avoid parsing issues
    .replace(/section\s+([^:]+):/g, (match, sectionName) => `section ${sectionName}：`)
    // Fix common syntax issues
    .replace(/fifopacket/g, 'rect')
    // Ensure graph has direction
    .replace(/^graph\s+((?:TB|BT|RL|LR)*)/, (match, direction) => {
      return direction ? match : 'graph TD'
    })
    // Clean up empty lines and extra spaces
    .trim()
}

/**
 * Prepares mermaid code based on selected style
 */
export function prepareMermaidCode(code: string, style: 'classic' | 'handDrawn'): string {
  let finalCode = preprocessMermaidCode(code)

  // Special handling for gantt charts and mindmaps
  if (finalCode.trim().startsWith('gantt') || finalCode.trim().startsWith('mindmap')) {
    // For gantt charts and mindmaps, preserve the structure exactly as is
    return finalCode
  }

  if (style === 'handDrawn') {
    finalCode = finalCode
      // Remove style definitions that interfere with hand-drawn style
      .replace(/style\s+[^\n]+/g, '')
      .replace(/linkStyle\s+[^\n]+/g, '')
      .replace(/^flowchart/, 'graph')
      // Remove any styles that might interfere with hand-drawn style
      .replace(/class="[^"]*"/g, '')
      .replace(/fill="[^"]*"/g, '')
      .replace(/stroke="[^"]*"/g, '')

    // Ensure hand-drawn style charts always start with graph
    if (!finalCode.startsWith('graph') && !finalCode.startsWith('flowchart'))
      finalCode = `graph TD\n${finalCode}`
  }

  return finalCode
}

/**
 * Converts SVG to base64 string for image rendering
 */
export function svgToBase64(svgGraph: string): Promise<string> {
  if (!svgGraph)
    return Promise.resolve('')

  try {
    // Ensure SVG has correct XML declaration
    if (!svgGraph.includes('<?xml'))
      svgGraph = `<?xml version="1.0" encoding="UTF-8"?>${svgGraph}`

    const blob = new Blob([new TextEncoder().encode(svgGraph)], { type: 'image/svg+xml;charset=utf-8' })
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.onloadend = () => resolve(reader.result as string)
      reader.onerror = reject
      reader.readAsDataURL(blob)
    })
  }
  catch (error) {
    console.error('Error converting SVG to base64:', error)
    return Promise.resolve('')
  }
}

/**
 * Processes SVG for theme styling
 */
export function processSvgForTheme(
  svg: string,
  isDark: boolean,
  isHandDrawn: boolean,
  themes: {
    light: any
    dark: any
  },
): string {
  let processedSvg = svg

  if (isDark) {
    processedSvg = processedSvg
      .replace(/style="fill: ?#000000"/g, 'style="fill: #e2e8f0"')
      .replace(/style="stroke: ?#000000"/g, 'style="stroke: #94a3b8"')
      .replace(/<rect [^>]*fill="#ffffff"/g, '<rect $& fill="#1e293b"')

    if (isHandDrawn) {
      processedSvg = processedSvg
        .replace(/fill="#[a-fA-F0-9]{6}"/g, `fill="${themes.dark.nodeColors[0].bg}"`)
        .replace(/stroke="#[a-fA-F0-9]{6}"/g, `stroke="${themes.dark.connectionColor}"`)
        .replace(/stroke-width="1"/g, 'stroke-width="1.5"')
    }
    else {
      let i = 0
      themes.dark.nodeColors.forEach(() => {
        const regex = /fill="#[a-fA-F0-9]{6}"[^>]*class="node-[^"]*"/g
        processedSvg = processedSvg.replace(regex, (match: string) => {
          const colorIndex = i % themes.dark.nodeColors.length
          i++
          return match.replace(/fill="#[a-fA-F0-9]{6}"/, `fill="${themes.dark.nodeColors[colorIndex].bg}"`)
        })
      })

      processedSvg = processedSvg
        .replace(/<path [^>]*stroke="#[a-fA-F0-9]{6}"/g,
          `<path stroke="${themes.dark.connectionColor}" stroke-width="1.5"`)
        .replace(/<(line|polyline) [^>]*stroke="#[a-fA-F0-9]{6}"/g,
          `<$1 stroke="${themes.dark.connectionColor}" stroke-width="1.5"`)
    }
  }
  else {
    if (isHandDrawn) {
      processedSvg = processedSvg
        .replace(/fill="#[a-fA-F0-9]{6}"/g, `fill="${themes.light.nodeColors[0].bg}"`)
        .replace(/stroke="#[a-fA-F0-9]{6}"/g, `stroke="${themes.light.connectionColor}"`)
        .replace(/stroke-width="1"/g, 'stroke-width="1.5"')
    }
    else {
      themes.light.nodeColors.forEach(() => {
        const regex = /fill="#[a-fA-F0-9]{6}"[^>]*class="node-[^"]*"/g
        let i = 0
        processedSvg = processedSvg.replace(regex, (match: string) => {
          const colorIndex = i % themes.light.nodeColors.length
          i++
          return match.replace(/fill="#[a-fA-F0-9]{6}"/, `fill="${themes.light.nodeColors[colorIndex].bg}"`)
        })
      })

      processedSvg = processedSvg
        .replace(/<path [^>]*stroke="#[a-fA-F0-9]{6}"/g,
          `<path stroke="${themes.light.connectionColor}"`)
        .replace(/<(line|polyline) [^>]*stroke="#[a-fA-F0-9]{6}"/g,
          `<$1 stroke="${themes.light.connectionColor}"`)
    }
  }

  return processedSvg
}

/**
 * Checks if mermaid code is complete and valid
 */
export function isMermaidCodeComplete(code: string): boolean {
  if (!code || code.trim().length === 0)
    return false

  try {
    const trimmedCode = code.trim()

    // Special handling for gantt charts
    if (trimmedCode.startsWith('gantt')) {
      // For gantt charts, check if it has at least a title and one task
      const lines = trimmedCode.split('\n').filter(line => line.trim().length > 0)
      return lines.length >= 3
    }

    // Special handling for mindmaps
    if (trimmedCode.startsWith('mindmap')) {
      // For mindmaps, check if it has at least a root node
      const lines = trimmedCode.split('\n').filter(line => line.trim().length > 0)
      return lines.length >= 2
    }

    // Check for basic syntax structure
    const hasValidStart = /^(graph|flowchart|sequenceDiagram|classDiagram|classDef|class|stateDiagram|gantt|pie|er|journey|requirementDiagram|mindmap)/.test(trimmedCode)

    // Check for balanced brackets and parentheses
    const isBalanced = (() => {
      const stack = []
      const pairs = { '{': '}', '[': ']', '(': ')' }

      for (const char of trimmedCode) {
        if (char in pairs) {
          stack.push(char)
        }
        else if (Object.values(pairs).includes(char)) {
          const last = stack.pop()
          if (pairs[last as keyof typeof pairs] !== char)
            return false
        }
      }

      return stack.length === 0
    })()

    // Check for common syntax errors
    const hasNoSyntaxErrors = !trimmedCode.includes('undefined')
                           && !trimmedCode.includes('[object Object]')
                           && trimmedCode.split('\n').every(line =>
                             !(line.includes('-->') && !line.match(/\S+\s*-->\s*\S+/)))

    return hasValidStart && isBalanced && hasNoSyntaxErrors
  }
  catch (error) {
    console.debug('Mermaid code validation error:', error)
    return false
  }
}

/**
 * Helper to wait for DOM element with retry mechanism
 */
export function waitForDOMElement(callback: () => Promise<any>, maxAttempts = 3, delay = 100): Promise<any> {
  return new Promise((resolve, reject) => {
    let attempts = 0
    const tryRender = async () => {
      try {
        resolve(await callback())
      }
      catch (error) {
        attempts++
        if (attempts < maxAttempts)
          setTimeout(tryRender, delay)
        else
          reject(error)
      }
    }
    tryRender()
  })
}
