<script setup lang="ts">
import { computed, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
import { usePagesStore } from '~/stores/pages'

type BuilderBlockType = 'html' | 'image' | 'form' | 'kakao'

type BuilderBlock = {
  id: string
  type: BuilderBlockType
  label: string
  html?: string
  src?: string
  alt?: string
}

const route = useRoute()
const router = useRouter()
const pagesStore = usePagesStore()
const { campaignOptions } = storeToRefs(pagesStore)

const pageId = computed(() => String(route.params.id || ''))
const selectedPage = computed(() => pagesStore.pages.find((page) => page.id === pageId.value))

const pageTitle = ref('Landing Page')
const metaDescription = ref('landing page description')
const metaKeywords = ref('landing, ads')
const iconUrl = ref('https://avatars.githubusercontent.com/u/9919?s=200&v=4')
const headCode = ref('<meta property="og:type" content="website" />')
const bodyScript = ref("console.log('landing admin builder loaded')")
const footerHtml = ref('')
const isDragOver = ref(false)
const imageInputRef = ref<HTMLInputElement | null>(null)

const htmlDraft = ref('<p>새 HTML 블록입니다.</p>')
const imageAlt = ref('이미지')

const generatedHtml = ref('')
const isSaved = ref(false)
const objectUrlMap = ref<Record<string, string>>({})

const blockList = ref<BuilderBlock[]>([
  { id: `b-${Date.now()}`, type: 'html', label: '커스텀 HTML', html: '<p>커스텀 HTML 블록입니다.</p>' },
])

const campaignName = computed(() => {
  if (!selectedPage.value) return '-'
  return campaignOptions.value.find((campaign) => campaign.id === selectedPage.value?.campaignId)?.name || '-'
})

const pageUrl = computed(() => {
  if (!selectedPage.value) return ''
  return `https://${selectedPage.value.domain}${selectedPage.value.routePath}`
})

const previewHeader = computed(() => selectedPage.value?.name || '새 페이지')

const finalHeadHtml = computed(() => {
  const pieces = [
    '<meta charset="UTF-8" />',
    `<title>${escapeHtml(pageTitle.value)}</title>`,
    `<meta name="description" content="${escapeHtml(metaDescription.value)}" />`,
    `<meta name="keywords" content="${escapeHtml(metaKeywords.value)}" />`,
    `<link rel="icon" href="${escapeHtml(iconUrl.value)}" />`,
    headCode.value.trim(),
  ]

  return pieces.filter(Boolean).join('\n  ')
})

const blockHtmls = computed(() => blockList.value.map((block) => {
  if (block.type === 'image' && block.src) {
    return `<img src="${escapeHtml(block.src)}" alt="${escapeHtml(block.alt || '')}" style="max-width:100%;border-radius:12px;display:block;" />`
  }

  return block.html ? block.html : '<p>빈 HTML</p>'
}))

const previewBlockHtmls = computed(() => blockList.value.map((block) => {
  if (block.type === 'image' && block.src) {
    return `<img src="${escapeHtml(block.src)}" alt="${escapeHtml(block.alt || '')}" style="max-width:320px; width:100%; max-height:220px; object-fit:contain;display:block;" />`
  }

  return block.html ? block.html : '<p>빈 HTML</p>'
}))

const finalBodyHtml = computed(() => {
  const bodyOpen = '<' + 'script>'
  const bodyClose = '<' + '/script>'
  const safeBodyScript = bodyScript.value.replace(/<\/script/gi, '<\\/script')
  const body = [
    ...blockHtmls.value,
    footerHtml.value,
    `${bodyOpen}${safeBodyScript}${bodyClose}`,
  ].join('\n')

  return `<!doctype html>
<html>
<head>
${finalHeadHtml.value}
</head>
<body>
<div style="padding:16px;">${body}</div>
</body>
</html>`
})

const previewBodyHtml = computed(() => {
  const body = [
    ...previewBlockHtmls.value,
    footerHtml.value,
  ].join('\n')

  return `<div style=\"padding:16px;\">${body}</div>`
})

const addHtmlBlock = () => {
  const draft = htmlDraft.value.trim() || '<p>빈 HTML</p>'
  blockList.value = [
    {
      id: `b-html-${Date.now()}`,
      type: 'html',
      label: `HTML 블록 ${blockList.value.length + 1}`,
      html: draft,
    },
    ...blockList.value,
  ]
  htmlDraft.value = '<p>새 HTML 블록입니다.</p>'
}

const addImageFromFiles = (files: FileList | null) => {
  if (!files || files.length === 0) return

  const toAdd = Array.from(files)
  const createdBlocks: BuilderBlock[] = toAdd.map((file, idx) => {
    const localUrl = URL.createObjectURL(file)
    const blockId = `b-image-${Date.now()}-${idx}`
    objectUrlMap.value[blockId] = localUrl
    return {
      id: blockId,
      type: 'image',
      label: `이미지 블록 ${blockList.value.length + idx + 1}`,
      src: localUrl,
      alt: imageAlt.value.trim() || '이미지',
    }
  })

  blockList.value = [...createdBlocks, ...blockList.value]
  imageAlt.value = '이미지'
}

const addImageFromUpload = (evt: Event) => {
  const target = evt.target as HTMLInputElement
  const targetFiles = target.files
  addImageFromFiles(targetFiles)

  target.value = ''
}

const openImagePicker = () => {
  imageInputRef.value?.click()
}

const onImageDragOver = (evt: DragEvent) => {
  evt.preventDefault()
  isDragOver.value = true
}

const onImageDragLeave = (evt: DragEvent) => {
  evt.preventDefault()
  isDragOver.value = false
}

const onImageDrop = (evt: DragEvent) => {
  evt.preventDefault()
  isDragOver.value = false
  addImageFromFiles(evt.dataTransfer?.files || null)
}

const moveUp = (index: number) => {
  if (index === 0) return
  const next = [...blockList.value]
  ;[next[index - 1], next[index]] = [next[index], next[index - 1]]
  blockList.value = next
}

const moveDown = (index: number) => {
  if (index === blockList.value.length - 1) return
  const next = [...blockList.value]
  ;[next[index], next[index + 1]] = [next[index + 1], next[index]]
  blockList.value = next
}

const removeBlock = (id: string) => {
  if (objectUrlMap.value[id]) {
    URL.revokeObjectURL(objectUrlMap.value[id])
    delete objectUrlMap.value[id]
  }
  blockList.value = blockList.value.filter((block) => block.id !== id)
}

const saveBuilder = () => {
  generatedHtml.value = finalBodyHtml.value
  isSaved.value = true
  setTimeout(() => {
    isSaved.value = false
  }, 1200)
}

const copyFinalHtml = async () => {
  if (!generatedHtml.value) {
    generatedHtml.value = finalBodyHtml.value
  }

  await navigator.clipboard?.writeText(generatedHtml.value)
}

const backToList = () => {
  router.push('/admin/pages')
}

function escapeHtml(value: string) {
  return value
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&#039;')
}
</script>

<template>
  <section class="space-y-5">
    <header class="rounded-xl border border-slate-700/80 bg-slate-900 px-5 py-4">
      <div class="flex flex-wrap items-center justify-between gap-2">
        <div>
          <p class="text-xs text-slate-400">홈 &gt; 페이지 &gt; 빌더</p>
          <h1 class="mt-1 text-2xl font-black tracking-tight text-white">페이지 빌더</h1>
          <p class="mt-1 text-sm text-slate-400">선택한 페이지의 블록을 관리하고 HTML을 생성합니다.</p>
        </div>
        <div class="flex items-center gap-2">
          <NuxtLink to="/admin/pages" class="rounded-md border border-slate-700 px-3 py-2 text-sm">목록으로</NuxtLink>
          <button type="button" @click="backToList" class="rounded-md border border-slate-700 px-3 py-2 text-sm">닫기</button>
          <button type="button" @click="saveBuilder" class="rounded-md bg-gradient-to-r from-indigo-600 to-cyan-500 px-4 py-2 text-sm font-medium text-white">저장</button>
        </div>
      </div>
    </header>

    <section v-if="selectedPage" class="grid gap-4 lg:grid-cols-[1.2fr_1fr]">
      <article class="rounded-2xl border border-slate-800 bg-slate-950 p-5">
        <div class="mb-4">
          <h2 class="text-xl font-bold text-white">{{ previewHeader }}</h2>
          <p class="mt-1 text-sm text-slate-400">{{ campaignName }}</p>
          <p class="mt-1 text-sm text-slate-300">{{ pageUrl }}</p>
        </div>

        <div class="mx-auto w-[360px] rounded-xl border border-slate-700 bg-black/20 p-4">
            <div class="rounded-lg bg-slate-900/80 p-2 min-h-[120px]" v-html="previewBodyHtml"></div>
            <div v-if="blockHtmls.length === 0" class="rounded-lg border border-slate-700 bg-slate-900/80 p-2 mt-2 text-xs text-slate-300">블록이 없습니다.</div>
        </div>
      </article>

      <article class="rounded-2xl border border-slate-800 bg-slate-950 p-5 text-sm">
        <h2 class="text-lg font-semibold text-white">빌더 설정</h2>
        <p class="mt-1 text-slate-400">HTML/이미지 블록과 헤더/아이콘/Body Script/푸터 HTML을 설정하세요.</p>

        <div class="mt-4 space-y-2">
          <label class="block space-y-1">
            <span class="text-slate-400">페이지 제목</span>
            <input v-model="pageTitle" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2" />
          </label>
          <label class="block space-y-1">
            <span class="text-slate-400">메타 설명</span>
            <textarea v-model="metaDescription" rows="2" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2"></textarea>
          </label>
          <label class="block space-y-1">
            <span class="text-slate-400">메타 키워드</span>
            <input v-model="metaKeywords" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2" />
          </label>
          <label class="block space-y-1">
            <span class="text-slate-400">파비콘 URL</span>
            <input v-model="iconUrl" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2" />
          </label>
          <label class="block space-y-1">
            <span class="text-slate-400">HEAD 추가 코드</span>
            <textarea v-model="headCode" rows="3" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2"></textarea>
          </label>
          <label class="block space-y-1">
            <span class="text-slate-400">BODY Script</span>
            <textarea v-model="bodyScript" rows="3" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2"></textarea>
          </label>
          <label class="block space-y-1">
            <span class="text-slate-400">Footer HTML</span>
            <textarea v-model="footerHtml" rows="3" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2"></textarea>
          </label>
        </div>

        <div class="mt-4 space-y-2">
          <h3 class="font-semibold text-white">블록 추가</h3>
          <label class="block space-y-1">
            <span class="text-slate-400">HTML 블록</span>
            <textarea v-model="htmlDraft" rows="3" class="w-full rounded-md border border-slate-700 bg-slate-950 px-3 py-2"></textarea>
          </label>
          <button type="button" @click="addHtmlBlock" class="mt-1 rounded-md bg-cyan-900/60 px-3 py-2 text-sm text-white">HTML 블록 추가</button>

          <div
            class="mt-3 rounded-lg border-2 border-dashed border-slate-700 bg-slate-900/40 p-5 text-center text-slate-300"
            :class="isDragOver ? 'border-cyan-400 bg-slate-900' : 'border-slate-700'"
            @dragover.prevent="onImageDragOver"
            @dragleave.prevent="onImageDragLeave"
            @drop.prevent="onImageDrop"
            @click="openImagePicker"
          >
            <p class="text-sm text-slate-200 font-semibold">이미지 파일을 드래그해서 올려주세요</p>
            <p class="mt-1 text-xs text-slate-500">갯수 제한 없이 한 번에 여러 장 추가됩니다.</p>
            <span class="text-xs text-slate-500 mt-2 block">참고: 업로드한 파일은 현재 페이지 미리보기/블록으로 즉시 반영됩니다.</span>
            <input
              ref="imageInputRef"
              type="file"
              accept="image/*"
              multiple
              class="hidden"
              @change="addImageFromUpload"
            />
          </div>
        </div>

        <div class="mt-4 space-y-2">
          <div v-for="(block, idx) in blockList" :key="block.id" class="rounded-md border border-slate-700 bg-slate-900 px-3 py-2">
            <div class="mb-1 flex items-start justify-between gap-2">
              <div class="flex min-w-0 items-center gap-2">
                <img
                  v-if="block.type === 'image' && block.src"
                  :src="block.src"
                  :alt="block.alt || '이미지'"
                  class="h-12 w-16 rounded-none object-cover"
                />
                <div class="min-w-0">
                  <p class="text-slate-100">{{ block.label }}</p>
                  <p class="text-xs text-slate-400">{{ block.type }}</p>
                  <p class="text-xs text-slate-300" v-if="block.type === 'html'">{{ block.html }}</p>
                  <p class="text-xs text-slate-300" v-else-if="block.type === 'image'">{{ block.alt || '이미지 블록' }}</p>
                  <p class="text-xs text-slate-300" v-else>{{ block.html || '사용자 블록' }}</p>
                </div>
              </div>
              <div class="flex items-center gap-2">
                <button type="button" class="rounded-md border border-slate-700 px-2 py-1 text-xs" @click="moveUp(idx)">↑</button>
                <button type="button" class="rounded-md border border-slate-700 px-2 py-1 text-xs" @click="moveDown(idx)">↓</button>
                <button type="button" class="rounded-md border border-red-500/50 px-2 py-1 text-xs text-red-200" @click="removeBlock(block.id)">삭제</button>
              </div>
            </div>
          </div>
        </div>

        <p class="mt-4 text-xs text-slate-400">{{ blockList.length }}개 블록</p>
      </article>
    </section>

    <section v-else class="rounded-2xl border border-dashed border-slate-700 bg-slate-900 p-6 text-slate-300">
      <p>선택한 페이지를 찾을 수 없습니다.</p>
      <NuxtLink to="/admin/pages" class="mt-4 inline-flex rounded-md border border-slate-700 px-3 py-1.5 text-sm text-slate-100">페이지 목록으로 이동</NuxtLink>
    </section>

    <section v-if="generatedHtml" class="rounded-2xl border border-slate-700 bg-slate-900 p-4">
      <div class="flex items-center justify-between">
        <h3 class="text-sm font-semibold text-slate-100">생성 HTML</h3>
        <button type="button" @click="copyFinalHtml" class="rounded-md border border-cyan-300/40 px-3 py-1.5 text-xs text-cyan-100">클립보드 복사</button>
      </div>
      <pre class="mt-3 max-h-64 overflow-auto rounded-lg bg-slate-950 p-3 text-xs text-slate-300">{{ generatedHtml }}</pre>
    </section>

    <p v-if="isSaved" class="rounded-md border border-emerald-300/40 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-200">저장(HTML 생성)되었습니다.</p>
  </section>
</template>
