import { LEFT } from '../const'
import type { Topic, Wrapper, Parent, Children, Expander } from '../types/dom'
import type { MindElixirInstance, NodeObj } from '../types/index'
import { encodeHTML, getOffsetLT } from '../utils/index'
import { layoutChildren } from './layout'
import { marked } from 'marked'
// 移除imageProcessor引用，使用MindElixir原生image属性


// DOM manipulation
const $d = document
export const findEle = function (this: MindElixirInstance, id: string, el?: HTMLElement) {
  const scope = this?.el ? this.el : el ? el : document
  const ele = scope.querySelector<Topic>(`[data-nodeid="me${id}"]`)
  if (!ele) throw new Error(`FindEle: Node ${id} not found, maybe it's collapsed.`)
  return ele
}

export const shapeTpc = function (this: MindElixirInstance, tpc: Topic, nodeObj: NodeObj) {
  tpc.innerHTML = ''

  if (nodeObj.style) {
    const style = nodeObj.style
    type KeyOfStyle = keyof typeof style
    for (const key in style) {
      tpc.style[key as KeyOfStyle] = style[key as KeyOfStyle]!
    }
  }

  if (nodeObj.dangerouslySetInnerHTML) {
    // 清理HTML内容，移除重复的格式
    let cleanedHTML = nodeObj.dangerouslySetInnerHTML
    
    // 检查是否包含表格，如果包含表格则不进行列表处理
    const hasTable = cleanedHTML.includes('<table') || cleanedHTML.includes('<td>') || cleanedHTML.includes('<th>')
    
    if (!hasTable) {
      // 移除• 【这种重复格式
      cleanedHTML = cleanedHTML.replace(/•\s*【/g, '【')
      cleanedHTML = cleanedHTML.replace(/•\s*\[/g, '[')
      
      // 移除其他可能的重复格式
      cleanedHTML = cleanedHTML.replace(/•\s*（/g, '（')
      cleanedHTML = cleanedHTML.replace(/•\s*\(/g, '(')
      
      // 处理换行符和列表格式
      // 将换行符转换为<br>标签，但保持列表结构
      cleanedHTML = cleanedHTML
        // 处理列表项：将每个•开头的行转换为<li>
        .replace(/^(\s*)•\s*(.+)$/gm, '<li>$2</li>')
        // 将连续的<li>标签包装在<ul>中
        .replace(/(<li>.*<\/li>)/gs, (match) => {
          // 如果已经被<ul>包装，不重复包装
          if (cleanedHTML.includes('<ul>')) return match
          return `<ul>${match}</ul>`
        })
        // 将剩余的换行符转换为<br>
        .replace(/\n/g, '<br>')
    } else {
      // 对于表格内容，只移除重复格式，不进行列表处理
      cleanedHTML = cleanedHTML.replace(/•\s*【/g, '【')
      cleanedHTML = cleanedHTML.replace(/•\s*\[/g, '[')
      cleanedHTML = cleanedHTML.replace(/•\s*（/g, '（')
      cleanedHTML = cleanedHTML.replace(/•\s*\(/g, '(')
    }
    
    tpc.innerHTML = cleanedHTML
    
    // 检查是否包含图片，决定文本对齐方式
    const hasImages = cleanedHTML.includes('<img')
    const hasNodeImage = !!nodeObj.image
    const hasAnyImage = hasImages || hasNodeImage
    
    // 统一使用左对齐样式，简化逻辑
    tpc.classList.add('no-image')
    tpc.classList.remove('has-image')
    
    return
  }

  if (nodeObj.image) {
    const img = nodeObj.image
    if (img.url && img.width && img.height) {
      const imgEl = $d.createElement('img')
      // Use imageProxy function if provided, otherwise use original URL
      imgEl.src = this.imageProxy ? this.imageProxy(img.url) : img.url
      imgEl.style.width = img.width + 'px'
      imgEl.style.height = img.height + 'px'
      if (img.fit) imgEl.style.objectFit = img.fit
      tpc.appendChild(imgEl)
      tpc.image = imgEl
    } else {
      console.warn('Image url/width/height are required')
    }
  } else if (tpc.image) {
    tpc.image = undefined
  }

  {
    const textEl = $d.createElement('span')
    textEl.className = 'text'

    // Check if markdown parser is provided and topic contains markdown syntax
    let content = ''
    if (this.markdown) {
      content = this.markdown(nodeObj.topic, nodeObj)
    } else {
      // 直接设置文本内容，图片通过MindElixir原生image属性处理
      content = nodeObj.topic || ''
    }
    
    // 清理文本内容，移除重复的格式
    content = content.replace(/•\s*【/g, '【')
    content = content.replace(/•\s*\[/g, '[')
    content = content.replace(/•\s*（/g, '（')
    content = content.replace(/•\s*\(/g, '(')
    
    textEl.innerHTML = content
    tpc.appendChild(textEl)
    tpc.text = textEl
    
    // 检查是否有图片，决定文本对齐方式
    const hasNodeImage = !!nodeObj.image
    const hasImageInText = content.includes('<img')
    const hasAnyImage = hasNodeImage || hasImageInText
    
    // 统一使用左对齐样式，简化逻辑
    tpc.classList.add('no-image')
    tpc.classList.remove('has-image')
  }

  if (nodeObj.hyperLink) {
    const linkEl = $d.createElement('a')
    linkEl.className = 'hyper-link'
    linkEl.target = '_blank'
    linkEl.innerText = '🔗'
    linkEl.href = nodeObj.hyperLink
    tpc.appendChild(linkEl)
    tpc.link = linkEl
  } else if (tpc.link) {
    tpc.link = undefined
  }

  if (nodeObj.icons && nodeObj.icons.length) {
    const iconsEl = $d.createElement('span')
    iconsEl.className = 'icons'
    iconsEl.innerHTML = nodeObj.icons.map(icon => `<span>${encodeHTML(icon)}</span>`).join('')
    tpc.appendChild(iconsEl)
    tpc.icons = iconsEl
  } else if (tpc.icons) {
    tpc.icons = undefined
  }

  if (nodeObj.tags && nodeObj.tags.length) {
    const tagsEl = $d.createElement('div')
    tagsEl.className = 'tags'

    nodeObj.tags.forEach(tag => {
      const span = $d.createElement('span')

      if (typeof tag === 'string') {
        span.textContent = tag
      } else {
        span.textContent = tag.text
        if (tag.className) {
          span.className = tag.className
        }
        if (tag.style) {
          Object.assign(span.style, tag.style)
        }
      }

      tagsEl.appendChild(span)
    })

    tpc.appendChild(tagsEl)
    tpc.tags = tagsEl
  } else if (tpc.tags) {
    tpc.tags = undefined
  }
}

// everything start from `Wrapper`
export const createWrapper = function (this: MindElixirInstance, nodeObj: NodeObj, omitChildren?: boolean) {
  const grp = $d.createElement('me-wrapper') as Wrapper
  const { p, tpc } = this.createParent(nodeObj)
  grp.appendChild(p)
  if (!omitChildren && nodeObj.children && nodeObj.children.length > 0) {
    const expander = createExpander(nodeObj.expanded)
    p.appendChild(expander)
    // tpc.expander = expander
    if (nodeObj.expanded !== false) {
      const children = layoutChildren(this, nodeObj.children)
      grp.appendChild(children)
    }
  }
  return { grp, top: p, tpc }
}

export const createParent = function (this: MindElixirInstance, nodeObj: NodeObj) {
  const p = $d.createElement('me-parent') as Parent
  const tpc = this.createTopic(nodeObj)
  shapeTpc.call(this, tpc, nodeObj)
  p.appendChild(tpc)
  
  return { p, tpc }
}


export const createChildren = function (this: MindElixirInstance, wrappers: Wrapper[]) {
  const children = $d.createElement('me-children') as Children
  children.append(...wrappers)
  return children
}

export const createTopic = function (this: MindElixirInstance, nodeObj: NodeObj) {
  const topic = $d.createElement('me-tpc') as Topic
  topic.nodeObj = nodeObj
  topic.dataset.nodeid = 'me' + nodeObj.id
  topic.draggable = this.draggable
  return topic
}

export function selectText(div: HTMLElement) {
  const range = $d.createRange()
  range.selectNodeContents(div)
  const getSelection = window.getSelection()
  if (getSelection) {
    getSelection.removeAllRanges()
    getSelection.addRange(range)
  }
}

export const editTopic = function (this: MindElixirInstance, el: Topic) {
  console.time('editTopic')
  if (!el) return
  const div = $d.createElement('div')
  const node = el.nodeObj

  // Get the original content from topic
  const originalContent = node.topic

  el.appendChild(div)
  div.id = 'input-box'
  div.textContent = originalContent
  div.contentEditable = 'plaintext-only'
  div.spellcheck = false
  const style = getComputedStyle(el)
  div.style.cssText = `min-width:${el.offsetWidth - 8}px;
  color:${style.color};
  padding:${style.padding};
  margin:${style.margin};
  font:${style.font};
  background-color:${style.backgroundColor !== 'rgba(0, 0, 0, 0)' && style.backgroundColor};
  border-radius:${style.borderRadius};`
  if (this.direction === LEFT) div.style.right = '0'

  selectText(div)

  this.bus.fire('operation', {
    name: 'beginEdit',
    obj: el.nodeObj,
  })

  div.addEventListener('keydown', e => {
    e.stopPropagation()
    const key = e.key

    if (key === 'Enter' || key === 'Tab') {
      // keep wrap for shift enter
      if (e.shiftKey) return

      e.preventDefault()
      div.blur()
      this.container.focus()
    }
  })

  div.addEventListener('blur', () => {
    if (!div) return
    const inputContent = div.textContent?.trim() || ''

    if (inputContent === '') {
      node.topic = originalContent
    } else {
      // Update topic content
      node.topic = inputContent

      if (this.markdown) {
        el.text.innerHTML = this.markdown(node.topic, node)
      } else {
        // Plain text content
        el.text.textContent = inputContent
      }
    }

    div.remove()

    // 重新应用样式和清理逻辑
    shapeTpc.call(this, el, node)

    if (inputContent === originalContent) return

    this.linkDiv()
    this.bus.fire('operation', {
      name: 'finishEdit',
      obj: node,
      origin: originalContent,
    })
  })
  console.timeEnd('editTopic')
}

export const createExpander = function (expanded: boolean | undefined): Expander {
  const expander = $d.createElement('me-epd') as Expander
  // if expanded is undefined, treat as expanded
  expander.expanded = expanded !== false
  expander.className = expanded !== false ? 'minus' : ''
  return expander
}

// 表格编辑功能
export const editTableNode = function (this: MindElixirInstance, el: Topic) {
  console.time('editTableNode')
  if (!el) return
  
  const node = el.nodeObj
  const originalHTML = node.dangerouslySetInnerHTML || ''
  
  // 创建遮罩层
  const overlay = $d.createElement('div')
  overlay.id = 'table-edit-overlay'
  overlay.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 9999;
  `
  
  // 创建编辑容器 - 使用fixed定位，居中显示
  const editContainer = $d.createElement('div')
  editContainer.id = 'table-edit-container'
  editContainer.style.cssText = `
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 600px;
    min-height: 400px;
    max-height: 80vh;
    background: white;
    border: 2px solid #660874;
    border-radius: 8px;
    padding: 15px;
    z-index: 10000;
    box-shadow: 0 8px 24px rgba(0,0,0,0.3);
    display: flex;
    flex-direction: column;
  `
  
  // 创建标题
  const title = $d.createElement('div')
  title.textContent = '编辑表格（Markdown格式）'
  title.style.cssText = `
    font-size: 14px;
    font-weight: 600;
    color: #333;
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid #e0e0e0;
  `
  
  // 创建文本区域用于编辑表格markdown
  const textarea = $d.createElement('textarea')
  textarea.value = this.convertTableHTMLToMarkdown(originalHTML)
  textarea.style.cssText = `
    flex: 1;
    min-height: 300px;
    border: 1px solid #ddd;
    border-radius: 4px;
    padding: 12px;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
    font-size: 13px;
    line-height: 1.5;
    resize: vertical;
    outline: none;
    background: #fafafa;
    color: #333;
    caret-color: #660874;
  `
  textarea.setAttribute('spellcheck', 'false')
  textarea.setAttribute('autocomplete', 'off')
  textarea.setAttribute('autocorrect', 'off')
  textarea.setAttribute('autocapitalize', 'off')
  
  // 创建按钮容器
  const buttonContainer = $d.createElement('div')
  buttonContainer.style.cssText = `
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #e0e0e0;
  `
  
  // 创建提示文字
  const hint = $d.createElement('span')
  hint.textContent = '提示: Ctrl+Enter保存, Esc取消'
  hint.style.cssText = `
    font-size: 11px;
    color: #999;
  `
  
  // 创建按钮组
  const buttonGroup = $d.createElement('div')
  buttonGroup.style.cssText = `
    display: flex;
    gap: 8px;
  `
  
  // 创建取消按钮
  const cancelButton = $d.createElement('button')
  cancelButton.textContent = '取消'
  cancelButton.style.cssText = `
    padding: 8px 20px;
    background: #6c757d;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 13px;
    transition: background 0.2s;
  `
  cancelButton.addEventListener('mouseenter', () => {
    cancelButton.style.background = '#5a6268'
  })
  cancelButton.addEventListener('mouseleave', () => {
    cancelButton.style.background = '#6c757d'
  })
  
  // 创建保存按钮
  const saveButton = $d.createElement('button')
  saveButton.textContent = '保存'
  saveButton.style.cssText = `
    padding: 8px 20px;
    background: #660874;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    transition: background 0.2s;
  `
  saveButton.addEventListener('mouseenter', () => {
    saveButton.style.background = '#4d0655'
  })
  saveButton.addEventListener('mouseleave', () => {
    saveButton.style.background = '#660874'
  })
  
  buttonGroup.appendChild(cancelButton)
  buttonGroup.appendChild(saveButton)
  buttonContainer.appendChild(hint)
  buttonContainer.appendChild(buttonGroup)
  
  editContainer.appendChild(title)
  editContainer.appendChild(textarea)
  editContainer.appendChild(buttonContainer)
  
  // 添加到body（因为使用了fixed定位）
  $d.body.appendChild(overlay)
  $d.body.appendChild(editContainer)
  
  // 点击遮罩层关闭编辑器
  overlay.addEventListener('click', () => {
    overlay.remove()
    editContainer.remove()
  })
  
  // 延迟聚焦，确保DOM已渲染
  setTimeout(() => {
    textarea.focus()
    textarea.setSelectionRange(0, 0)  // 光标移到开始
    console.log('📊 编辑器已聚焦，光标应该可见')
  }, 50)
  
  // 保存功能
  const saveTable = () => {
    const newMarkdown = textarea.value.trim()
    
    console.log('📊 保存表格，原始markdown:', newMarkdown)
    
    if (newMarkdown === this.convertTableHTMLToMarkdown(originalHTML)) {
      // 没有变化，直接关闭
      console.log('📊 表格内容未变化，直接关闭')
      overlay.remove()
      editContainer.remove()
      return
    }
    
    // 配置marked
    marked.setOptions({
      breaks: false,
      gfm: true,
    })
    
    // 转换markdown为HTML (marked.parse返回Promise或string)
    let newHTML = marked.parse(newMarkdown) as string
    console.log('📊 转换后的HTML:', newHTML)
    
    // 为表格添加样式类
    const styledHTML = newHTML.replace(/<table>/g, '<table class="markdown-table">')
    
    console.log('📊 更新节点，新HTML长度:', styledHTML.length)
    
    // 移除编辑容器和遮罩层
    overlay.remove()
    editContainer.remove()
    
    // 更新节点数据
    node.dangerouslySetInnerHTML = styledHTML
    node.topic = newMarkdown  // 同时保存markdown原文
    
    console.log('📊 直接更新DOM内容')
    // 直接更新DOM，不调用shapeTpc（因为shapeTpc会清空innerHTML）
    el.innerHTML = styledHTML
    
    // 触发操作历史记录，确保数据持久化
    this.bus.fire('operation', {
      name: 'finishEditTable',
      obj: node,
      origin: originalHTML,
    })
    
    // 添加样式类
    el.classList.add('no-image')
    el.classList.remove('has-image')
    
    console.log('📊 触发操作事件')
    // 触发操作事件
    this.bus.fire('operation', {
      name: 'finishEditTable',
      obj: node,
      origin: originalHTML,
    })
    
    console.log('📊 重新布局')
    this.linkDiv()
  }
  
  // 取消功能
  const cancelEdit = () => {
    overlay.remove()
    editContainer.remove()
  }
  
  // 绑定事件
  saveButton.addEventListener('click', saveTable)
  cancelButton.addEventListener('click', cancelEdit)
  
  // 键盘事件
  textarea.addEventListener('keydown', (e) => {
    e.stopPropagation()
    if (e.key === 'Escape') {
      e.preventDefault()
      cancelEdit()
    } else if (e.key === 'Enter' && e.ctrlKey) {
      e.preventDefault()
      saveTable()
    }
  })
  
  console.timeEnd('editTableNode')
}

// 将表格HTML转换为markdown
export const convertTableHTMLToMarkdown = function (this: MindElixirInstance, html: string): string {
  // 创建临时DOM元素
  const tempDiv = $d.createElement('div')
  tempDiv.innerHTML = html
  
  const table = tempDiv.querySelector('table')
  if (!table) return html
  
  let markdown = ''
  
  // 处理表头
  const thead = table.querySelector('thead')
  if (thead) {
    const headerRow = thead.querySelector('tr')
    if (headerRow) {
      const headers = Array.from(headerRow.querySelectorAll('th')).map(th => th.textContent?.trim() || '')
      markdown += '| ' + headers.join(' | ') + ' |\n'
      markdown += '| ' + headers.map(() => '---').join(' | ') + ' |\n'
    }
  }
  
  // 处理表体
  const tbody = table.querySelector('tbody')
  if (tbody) {
    const rows = tbody.querySelectorAll('tr')
    rows.forEach(row => {
      const cells = Array.from(row.querySelectorAll('td')).map(td => td.textContent?.trim() || '')
      markdown += '| ' + cells.join(' | ') + ' |\n'
    })
  }
  
  return markdown.trim()
}
