<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import Editor from '@toast-ui/editor'
import '@toast-ui/editor/dist/toastui-editor.css'
import codeSyntaxHighlight from '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight-all'
import 'prismjs/themes/prism-tomorrow.css'
import '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css'
import { imageToBlob } from '@/utils/receiptOcr'
import { boardApi } from '@/api/boardApi'

const props = defineProps({
  modelValue: { type: String, default: '' },
  height: { type: String, default: '400px' },
  placeholder: { type: String, default: '' },
  initialEditType: { type: String, default: 'wysiwyg' }, // 'markdown' | 'wysiwyg'
})
const emit = defineEmits(['update:modelValue'])

const el = ref(null)
const imgInput = ref(null)
let editor = null
// 에디터가 마지막으로 emit 한 값. 부모가 되돌려준 echo 를 구분해 입력 중 setMarkdown 으로 끊기지 않게.
let lastEmitted = props.modelValue || ''

// 이미지: 압축 후 서버 업로드 → URL (base64 대신 본문엔 짧은 URL 만)
async function uploadCompressed(fileOrBlob) {
  const blob = await imageToBlob(fileOrBlob, 1280) // 긴 변 1280px, JPEG 0.85
  const { url } = await boardApi.uploadImage(blob)
  return url
}

// 커스텀 이미지 버튼 클릭 → 파일 선택 → 업로드 → 에디터에 삽입
// (Toast UI 기본 이미지 팝업이 작은 댓글창에서 잘려 OK 를 못 누르는 문제 회피)
async function onImagePick(e) {
  const file = e.target.files?.[0]
  e.target.value = ''
  if (!file || !editor) return
  try {
    const url = await uploadCompressed(file)
    const alt = file.name.replace(/\.[^.]+$/, '')
    editor.exec('addImage', { imageUrl: url, altText: alt })
  } catch {
    /* 업로드 실패 시 미삽입 */
  }
}

function makeImageButton() {
  const btn = document.createElement('button')
  btn.type = 'button'
  btn.className = 'toastui-editor-toolbar-icons image'
  btn.style.margin = '0'
  btn.setAttribute('aria-label', '이미지')
  btn.addEventListener('click', (ev) => {
    ev.preventDefault()
    imgInput.value?.click()
  })
  return btn
}

onMounted(() => {
  editor = new Editor({
    el: el.value,
    height: props.height,
    initialEditType: props.initialEditType,
    hideModeSwitch: true, // 마크다운/위지윅 전환 탭 숨김 (WYSIWYG 전용)
    plugins: [codeSyntaxHighlight], // 코드 구문 강조
    initialValue: props.modelValue || '',
    placeholder: props.placeholder,
    usageStatistics: false,
    autofocus: false,
    // 기본 이미지 버튼(팝업)을 커스텀(바로 업로드)으로 교체
    toolbarItems: [
      ['heading', 'bold', 'italic', 'strike'],
      ['hr', 'quote'],
      ['ul', 'ol', 'task', 'indent', 'outdent'],
      ['table', { name: 'image', tooltip: '이미지', el: makeImageButton() }, 'link'],
      ['code', 'codeblock'],
    ],
    events: {
      change: () => {
        lastEmitted = editor.getMarkdown()
        emit('update:modelValue', lastEmitted)
      },
    },
  })
})

// 외부 값 변경(수정 로드, 제출 후 초기화 등)만 에디터에 반영. echo 는 무시.
watch(
  () => props.modelValue,
  (val) => {
    const v = val || ''
    if (v === lastEmitted) return
    if (editor && v !== editor.getMarkdown()) {
      lastEmitted = v
      editor.setMarkdown(v)
    }
  },
)

onBeforeUnmount(() => {
  editor?.destroy()
  editor = null
})
</script>

<template>
  <div>
    <div ref="el"></div>
    <input ref="imgInput" type="file" accept="image/*" hidden @change="onImagePick" />
  </div>
</template>

<!-- 전역(unscoped): Toast UI 팝업이 좁은 화면(댓글창 등)에서 좌측으로 넘쳐 잘리는 문제 →
     모바일에선 화면 중앙 모달로 띄워 항상 보이게 한다. -->
<style>
@media (max-width: 768px) {
  .toastui-editor-popup {
    position: fixed !important;
    left: 50% !important;
    top: 50% !important;
    right: auto !important;
    /* Toast UI 가 max-width:480px 에서 margin-left:-150px 를 줘서 좌측으로 밀려 잘림 → 취소 */
    margin: 0 !important;
    transform: translate(-50%, -50%) !important;
    max-width: 94vw !important;
    max-height: 80vh;
    overflow: auto;
    z-index: 1300;
  }
}
</style>
