<script setup>
const props = defineProps({
  initialPost: {
    type: Object,
    default: () => ({})
  },
  submitLabel: {
    type: String,
    default: '저장'
  },
  saving: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['submit'])

const slugTouched = ref(Boolean(props.initialPost.slug))
const editorMode = ref('write')
const contentTextarea = ref(null)

const form = reactive({
  title: props.initialPost.title || '',
  slug: props.initialPost.slug || '',
  excerpt: props.initialPost.excerpt || '',
  content: props.initialPost.content || '',
  featuredImage: props.initialPost.featuredImage || '',
  status: props.initialPost.status || 'draft',
  tagsText: props.initialPost.tags?.join(', ') || ''
})

/**
 * 문자열을 URL 슬러그로 변환
 * @param {string} value - 원본 문자열
 * @returns {string} 슬러그
 */
const toSlug = (value) => value
  .trim()
  .toLowerCase()
  .replace(/[^a-z0-9가-힣\s-]/g, '')
  .replace(/\s+/g, '-')
  .replace(/-+/g, '-')
  .replace(/^-|-$/g, '')

watch(() => form.title, (title) => {
  if (!slugTouched.value) {
    form.slug = toSlug(title)
  }
})

/**
 * 슬러그 직접 입력 상태 표시
 * @returns {void}
 */
const touchSlug = () => {
  slugTouched.value = true
  form.slug = toSlug(form.slug)
}

/**
 * 쉼표 구분 태그 문자열을 슬러그 배열로 변환
 * @param {string} value - 태그 입력 문자열
 * @returns {Array<string>} 태그 슬러그 목록
 */
const parseTags = (value) => [...new Set(value
  .split(',')
  .map((tag) => toSlug(tag))
  .filter(Boolean))]

/**
 * 본문 선택 영역에 마크다운 문법 삽입
 * @param {string} before - 선택 영역 앞에 넣을 문자열
 * @param {string} after - 선택 영역 뒤에 넣을 문자열
 * @param {string} fallback - 선택 영역이 없을 때 넣을 문자열
 * @returns {void}
 */
const insertMarkdown = (before, after = '', fallback = '') => {
  const textarea = contentTextarea.value

  if (!textarea) {
    form.content += fallback || before
    return
  }

  const start = textarea.selectionStart
  const end = textarea.selectionEnd
  const selectedText = form.content.slice(start, end)
  const insertText = selectedText
    ? `${before}${selectedText}${after}`
    : (fallback || `${before}${after}`)

  form.content = `${form.content.slice(0, start)}${insertText}${form.content.slice(end)}`

  nextTick(() => {
    textarea.focus()
    const cursor = start + insertText.length
    textarea.setSelectionRange(cursor, cursor)
  })
}

/**
 * 제목 문법 삽입
 * @returns {void}
 */
const insertHeading = () => {
  insertMarkdown('## ', '', '## 제목')
}

/**
 * 굵게 문법 삽입
 * @returns {void}
 */
const insertBold = () => {
  insertMarkdown('**', '**', '**강조**')
}

/**
 * 목록 문법 삽입
 * @returns {void}
 */
const insertList = () => {
  insertMarkdown('- ', '', '- 목록')
}

/**
 * 인용 문법 삽입
 * @returns {void}
 */
const insertQuote = () => {
  insertMarkdown('> ', '', '> 인용')
}

/**
 * 코드 블록 문법 삽입
 * @returns {void}
 */
const insertCodeBlock = () => {
  insertMarkdown('```\n', '\n```', '```\n코드\n```')
}

/**
 * 게시물 입력값 제출
 * @returns {void}
 */
const submitPost = () => {
  const publishedAt = form.status === 'published'
    ? props.initialPost.publishedAt || new Date().toISOString()
    : null

  emit('submit', {
    title: form.title.trim(),
    slug: toSlug(form.slug || form.title),
    excerpt: form.excerpt.trim(),
    content: form.content,
    featuredImage: form.featuredImage.trim() || null,
    status: form.status,
    publishedAt,
    tags: parseTags(form.tagsText)
  })
}
</script>

<template>
  <form class="admin-post-form grid gap-6" @submit.prevent="submitPost">
    <div class="admin-post-form__main grid gap-5 lg:grid-cols-[minmax(0,1fr)_18rem]">
      <section class="admin-post-form__content grid gap-4">
        <label class="admin-post-form__field grid gap-2 text-sm">
          <span class="admin-post-form__label font-medium">제목</span>
          <input
            v-model="form.title"
            class="admin-post-form__input rounded border border-line bg-white px-3 py-2"
            type="text"
            required
          >
        </label>

        <div class="admin-post-form__field grid gap-2 text-sm">
          <div class="admin-post-form__editor-header flex flex-wrap items-center justify-between gap-3">
            <span class="admin-post-form__label font-medium">본문</span>
            <div class="admin-post-form__mode flex rounded border border-line bg-white p-1 text-xs font-semibold">
              <button
                class="admin-post-form__mode-button rounded px-3 py-1"
                :class="editorMode === 'write' ? 'bg-[#15171a] text-white' : 'text-muted'"
                type="button"
                @click="editorMode = 'write'"
              >
                작성
              </button>
              <button
                class="admin-post-form__mode-button rounded px-3 py-1"
                :class="editorMode === 'preview' ? 'bg-[#15171a] text-white' : 'text-muted'"
                type="button"
                @click="editorMode = 'preview'"
              >
                미리보기
              </button>
            </div>
          </div>

          <div v-if="editorMode === 'write'" class="admin-post-form__editor grid gap-2">
            <div class="admin-post-form__toolbar flex flex-wrap gap-2">
              <button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertHeading">
                제목
              </button>
              <button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertBold">
                굵게
              </button>
              <button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertList">
                목록
              </button>
              <button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertQuote">
                인용
              </button>
              <button class="admin-post-form__tool rounded border border-line bg-white px-3 py-1.5 text-xs font-semibold" type="button" @click="insertCodeBlock">
                코드
              </button>
            </div>
            <textarea
              ref="contentTextarea"
              v-model="form.content"
              class="admin-post-form__textarea min-h-[28rem] rounded border border-line bg-white px-3 py-3 font-mono text-sm leading-6"
              required
            />
          </div>

          <AdminMarkdownPreview v-else :content="form.content" />
        </div>
      </section>

      <aside class="admin-post-form__settings grid content-start gap-4">
        <label class="admin-post-form__field grid gap-2 text-sm">
          <span class="admin-post-form__label font-medium">상태</span>
          <select v-model="form.status" class="admin-post-form__select rounded border border-line bg-white px-3 py-2">
            <option value="draft">초안</option>
            <option value="published">발행</option>
            <option value="private">비공개</option>
          </select>
        </label>

        <label class="admin-post-form__field grid gap-2 text-sm">
          <span class="admin-post-form__label font-medium">슬러그</span>
          <input
            v-model="form.slug"
            class="admin-post-form__input rounded border border-line bg-white px-3 py-2"
            type="text"
            pattern="[a-z0-9가-힣]+(-[a-z0-9가-힣]+)*"
            required
            @input="touchSlug"
          >
        </label>

        <label class="admin-post-form__field grid gap-2 text-sm">
          <span class="admin-post-form__label font-medium">요약</span>
          <textarea
            v-model="form.excerpt"
            class="admin-post-form__textarea min-h-24 rounded border border-line bg-white px-3 py-2"
          />
        </label>

        <label class="admin-post-form__field grid gap-2 text-sm">
          <span class="admin-post-form__label font-medium">태그</span>
          <input
            v-model="form.tagsText"
            class="admin-post-form__input rounded border border-line bg-white px-3 py-2"
            type="text"
          >
        </label>

        <label class="admin-post-form__field grid gap-2 text-sm">
          <span class="admin-post-form__label font-medium">대표 이미지 URL</span>
          <input
            v-model="form.featuredImage"
            class="admin-post-form__input rounded border border-line bg-white px-3 py-2"
            type="url"
          >
        </label>
      </aside>
    </div>

    <div class="admin-post-form__actions flex justify-end gap-3 border-t border-line pt-5">
      <NuxtLink class="admin-post-form__cancel rounded border border-line bg-white px-4 py-2 text-sm font-semibold" to="/admin/posts">
        취소
      </NuxtLink>
      <button
        class="admin-post-form__submit rounded bg-[#15171a] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50"
        type="submit"
        :disabled="saving"
      >
        {{ saving ? '저장 중' : submitLabel }}
      </button>
    </div>
  </form>
</template>
