<script setup>
definePageMeta({
  layout: 'admin'
})

const { data: posts } = await useFetch('/admin/api/posts', {
  default: () => []
})

const analyticsRangeOptions = [
  { label: '7일', days: 7 },
  { label: '30일', days: 30 },
  { label: '3개월', days: 90 },
  { label: '6개월', days: 180 },
  { label: '12개월', days: 365 }
]
const selectedAnalyticsDays = ref(30)
const analyticsQuery = computed(() => ({
  days: selectedAnalyticsDays.value
}))

const { data: analyticsSummary, refresh: refreshSummary } = await useFetch('/admin/api/analytics/summary', {
  query: analyticsQuery,
  default: () => ({
    todayVisitors: 0,
    visitorsLast7Days: 0,
    pageViewsLast30Days: 0,
    onlineNow: 0,
    loggedInNow: 0,
    avgEngagedSeconds: 0,
    scroll50Reach: 0,
    trends: []
  })
})

const topPostsQuery = computed(() => ({
  days: selectedAnalyticsDays.value,
  limit: 5
}))

const { data: topPosts, refresh: refreshTopPosts } = await useFetch('/admin/api/analytics/posts', {
  query: topPostsQuery,
  default: () => []
})

const { data: realtime, refresh: refreshRealtime } = await useFetch('/admin/api/analytics/realtime', {
  query: { limit: 20 },
  default: () => ({
    summary: {
      onlineNow: 0,
      loggedInNow: 0,
      anonymousNow: 0
    },
    sessions: []
  })
})

const publishedCount = computed(() => posts.value.filter((post) => post.status === 'published').length)
const draftCount = computed(() => posts.value.filter((post) => post.status === 'draft').length)
const analyticsRangeLabel = computed(() => {
  return analyticsRangeOptions.find((option) => option.days === selectedAnalyticsDays.value)?.label || '30일'
})
const trendRows = computed(() => analyticsSummary.value.trends || [])
const trendStartDay = computed(() => trendRows.value[0]?.day || '')
const trendEndDay = computed(() => trendRows.value[trendRows.value.length - 1]?.day || '')

/**
 * 초 단위 체류시간을 읽기 쉬운 문자열로 변환한다.
 * @param {number} seconds - 초
 * @returns {string} 표시 문자열
 */
const formatEngagedDuration = (seconds) => {
  const value = Number(seconds) || 0
  if (value < 60) {
    return `${value}초`
  }

  const minutes = Math.floor(value / 60)
  const remainSeconds = value % 60
  return remainSeconds > 0 ? `${minutes}분 ${remainSeconds}초` : `${minutes}분`
}

/**
 * 선택 기간의 추세 합계를 반환한다.
 * @param {'visitors' | 'avgEngagedSeconds' | 'scroll50Reach'} key - 추세 키
 * @returns {number} 합계 또는 평균
 */
const getTrendSummaryValue = (key) => {
  const rows = trendRows.value
  if (key === 'avgEngagedSeconds') {
    const nonZeroRows = rows.filter((row) => Number(row.avgEngagedSeconds || 0) > 0)
    if (!nonZeroRows.length) {
      return 0
    }

    const total = nonZeroRows.reduce((sum, row) => sum + Number(row.avgEngagedSeconds || 0), 0)
    return Math.round(total / nonZeroRows.length)
  }

  return rows.reduce((sum, row) => sum + Number(row[key] || 0), 0)
}

/**
 * 추세 값 표시 문자열을 반환한다.
 * @param {'visitors' | 'avgEngagedSeconds' | 'scroll50Reach'} key - 추세 키
 * @param {number} value - 값
 * @returns {string} 표시 문자열
 */
const formatTrendValue = (key, value) => {
  if (key === 'avgEngagedSeconds') {
    return formatEngagedDuration(value)
  }

  return `${Number(value || 0)}`
}

const chartMetrics = computed(() => [
  {
    key: 'visitors',
    title: '방문자수',
    label: `${getTrendSummaryValue('visitors')}명`
  },
  {
    key: 'avgEngagedSeconds',
    title: '평균 체류시간',
    label: formatEngagedDuration(getTrendSummaryValue('avgEngagedSeconds'))
  },
  {
    key: 'scroll50Reach',
    title: '50% 스크롤 도달',
    label: `${getTrendSummaryValue('scroll50Reach')}회`
  }
])

/**
 * 차트 막대 높이 비율을 반환한다.
 * @param {'visitors' | 'avgEngagedSeconds' | 'scroll50Reach'} key - 추세 키
 * @param {Object} row - 추세 행
 * @returns {number} 높이 %
 */
const getTrendBarHeight = (key, row) => {
  const rows = trendRows.value
  const maxValue = Math.max(...rows.map((item) => Number(item[key] || 0)), 0)

  if (maxValue <= 0) {
    return 3
  }

  const value = Number(row[key] || 0)
  return Math.max(Math.round((value / maxValue) * 100), value > 0 ? 8 : 3)
}

/**
 * 추세 시작·종료 날짜 라벨을 반환한다.
 * @param {string} day - YYYY-MM-DD
 * @returns {string} 날짜 라벨
 */
const formatTrendDayLabel = (day) => {
  if (!day) {
    return ''
  }

  const [, month, date] = day.split('-')
  return `${month}.${date}`
}

/**
 * 현재 접속자가 보고 있는 화면명을 반환한다.
 * @param {Object} session - 접속 세션
 * @returns {string} 화면명
 */
const getSessionViewingTitle = (session) => {
  if (session.postTitle) {
    return session.postTitle
  }

  if (session.path === '/') {
    return '홈'
  }

  return session.path || '알 수 없음'
}

let refreshTimer = null

onMounted(() => {
  refreshTimer = window.setInterval(() => {
    refreshSummary()
    refreshTopPosts()
    refreshRealtime()
  }, 30000)
})

onUnmounted(() => {
  if (refreshTimer) {
    window.clearInterval(refreshTimer)
  }
})

watch(selectedAnalyticsDays, () => {
  refreshSummary()
  refreshTopPosts()
})
</script>

<template>
  <section class="admin-dashboard">
    <div class="admin-dashboard__header border-b border-line bg-paper p-6">
      <p class="admin-dashboard__eyebrow text-xs font-semibold uppercase text-muted">
        Admin
      </p>
      <h1 class="admin-dashboard__title mt-2 text-3xl font-semibold">
        대시보드
      </h1>
    </div>
    <div class="admin-dashboard__body space-y-6 bg-paper p-6">
      <section class="admin-dashboard__summary flex flex-wrap items-center gap-x-8 gap-y-2 border border-line bg-white px-4 py-3 text-sm">
        <p class="admin-dashboard__summary-item text-muted">
          현재 접속자
          <strong class="ml-2 text-lg text-ink">{{ realtime.summary.onlineNow }}</strong>
        </p>
        <p class="admin-dashboard__summary-item text-muted">
          오늘 접속자
          <strong class="ml-2 text-lg text-ink">{{ analyticsSummary.todayVisitors }}</strong>
        </p>
        <p class="admin-dashboard__summary-item text-muted">
          게시물 수
          <strong class="ml-2 text-lg text-ink">{{ posts.length }}</strong>
          <span class="ml-1 text-xs">발행 {{ publishedCount }} · 초안 {{ draftCount }}</span>
        </p>
      </section>

      <section class="admin-dashboard__charts border border-line bg-white p-4">
        <div class="admin-dashboard__charts-header flex flex-wrap items-center justify-between gap-3">
          <div>
            <h2 class="admin-dashboard__section-title text-sm font-semibold text-ink">
              통계 추이
            </h2>
            <p class="admin-dashboard__section-description mt-1 text-xs text-muted">
              선택한 기간의 방문자수, 평균 체류시간, 50% 스크롤 도달 추이
            </p>
          </div>
          <div class="admin-dashboard__range flex flex-wrap gap-1">
            <button
              v-for="option in analyticsRangeOptions"
              :key="option.days"
              type="button"
              class="admin-dashboard__range-button border border-line px-3 py-1 text-xs font-medium text-muted hover:bg-paper hover:text-ink"
              :class="option.days === selectedAnalyticsDays ? 'bg-[#15171a] text-white hover:bg-[#15171a] hover:text-white' : 'bg-white'"
              @click="selectedAnalyticsDays = option.days"
            >
              {{ option.label }}
            </button>
          </div>
        </div>

        <div class="admin-dashboard__chart-grid mt-4 grid gap-4 lg:grid-cols-3">
          <article
            v-for="metric in chartMetrics"
            :key="metric.key"
            class="admin-dashboard__chart border border-line bg-paper p-4"
          >
            <div class="flex items-center justify-between gap-3">
              <p class="text-xs font-semibold uppercase text-muted">
                {{ metric.title }}
              </p>
              <strong class="text-sm text-ink">
                {{ metric.label }}
              </strong>
            </div>
            <div class="admin-dashboard__chart-bars mt-4 flex h-32 items-end gap-1 border-b border-line">
              <div
                v-for="row in trendRows"
                :key="`${metric.key}-${row.day}`"
                class="admin-dashboard__chart-bar-wrap flex min-w-[3px] flex-1 items-end"
                :title="`${row.day} · ${formatTrendValue(metric.key, row[metric.key])}`"
              >
                <div
                  class="admin-dashboard__chart-bar w-full bg-[#15171a]/80"
                  :style="{ height: `${getTrendBarHeight(metric.key, row)}%` }"
                />
              </div>
            </div>
            <div class="mt-2 flex justify-between text-[11px] text-muted">
              <span>{{ formatTrendDayLabel(trendStartDay) }}</span>
              <span>{{ analyticsRangeLabel }}</span>
              <span>{{ formatTrendDayLabel(trendEndDay) }}</span>
            </div>
          </article>
        </div>
      </section>

      <section class="admin-dashboard__live border border-line bg-white p-4">
        <div class="admin-dashboard__live-header flex items-center justify-between gap-4">
          <h2 class="admin-dashboard__section-title text-sm font-semibold text-ink">
            현재 접속자
          </h2>
          <p class="admin-dashboard__live-count text-xs text-muted">
            {{ realtime.sessions.length }}명 표시
          </p>
        </div>
        <ul
          v-if="realtime.sessions.length"
          class="admin-dashboard__live-list mt-4 divide-y divide-line"
        >
          <li
            v-for="session in realtime.sessions"
            :key="session.sessionHash"
            class="admin-dashboard__live-item flex items-center gap-3 py-3"
          >
            <img
              v-if="session.user?.avatarUrl"
              :src="session.user.avatarUrl"
              :alt="session.user.username"
              class="admin-dashboard__live-avatar h-9 w-9 shrink-0 rounded-full object-cover"
            >
            <div
              v-else
              class="admin-dashboard__live-avatar admin-dashboard__live-avatar--placeholder flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-paper text-xs font-semibold text-muted"
            >
              {{ session.isLoggedIn ? (session.user?.username || '?').slice(0, 1) : '?' }}
            </div>
            <div class="min-w-0 flex-1">
              <p class="admin-dashboard__live-name text-sm font-medium text-ink">
                {{ session.isLoggedIn ? session.user?.username : '익명 방문자' }}
              </p>
              <p class="admin-dashboard__live-path mt-0.5 truncate text-xs text-muted">
                {{ getSessionViewingTitle(session) }}
              </p>
            </div>
            <div class="admin-dashboard__live-meta shrink-0 text-right text-xs text-muted">
              <p class="font-medium text-ink">
                접속 유지 {{ formatEngagedDuration(session.durationSeconds) }}
              </p>
            </div>
          </li>
        </ul>
        <p
          v-else
          class="admin-dashboard__live-empty mt-4 text-sm text-muted"
        >
          현재 접속 중인 방문자가 없습니다.
        </p>
      </section>

      <section class="admin-dashboard__top-posts border border-line bg-white p-4">
        <h2 class="admin-dashboard__section-title text-sm font-semibold text-ink">
          인기 게시물 ({{ analyticsRangeLabel }})
        </h2>
        <ul
          v-if="topPosts.length"
          class="admin-dashboard__top-posts-list mt-4 space-y-3 text-sm"
        >
          <li
            v-for="(item, index) in topPosts"
            :key="item.id"
            class="admin-dashboard__top-posts-item flex items-start justify-between gap-4 border-b border-line pb-3 last:border-b-0 last:pb-0"
          >
            <div class="min-w-0 flex-1">
              <p class="admin-dashboard__top-posts-rank text-xs font-semibold uppercase text-muted">
                #{{ index + 1 }}
              </p>
              <NuxtLink
                :to="`/post/${item.slug}`"
                class="admin-dashboard__top-posts-title mt-1 block truncate font-medium text-ink hover:underline"
                target="_blank"
              >
                {{ item.title }}
              </NuxtLink>
            </div>
            <dl class="admin-dashboard__top-posts-stats shrink-0 text-right text-xs text-muted">
              <div>
                <dt class="inline">
                  조회
                </dt>
                <dd class="inline font-semibold text-ink">
                  {{ item.views }}
                </dd>
              </div>
              <div class="mt-1">
                <dt class="inline">
                  읽음
                </dt>
                <dd class="inline font-semibold text-ink">
                  {{ item.reads }}
                </dd>
              </div>
              <div class="mt-1">
                <dt class="inline">
                  체류
                </dt>
                <dd class="inline font-semibold text-ink">
                  {{ formatEngagedDuration(item.avgEngagedSeconds) }}
                </dd>
              </div>
              <div class="mt-1">
                <dt class="inline">
                  50/75/100%
                </dt>
                <dd class="inline font-semibold text-ink">
                  {{ item.scroll50 }}/{{ item.scroll75 }}/{{ item.scroll100 }}
                </dd>
              </div>
            </dl>
          </li>
        </ul>
        <p
          v-else
          class="admin-dashboard__top-posts-empty mt-4 text-sm text-muted"
        >
          아직 집계된 게시물 조회 데이터가 없습니다.
        </p>
      </section>
    </div>
  </section>
</template>
