<script setup lang="ts">
import { useAuthSession } from '../../../composables/useAuthSession'
import {
  formatOccurredOnDisplay,
  occurredOnToIsoAttr,
  occurredOnToLocalInputValue,
  parseLocalDatetimeInput,
} from '../../../utils/timeline-datetime'

definePageMeta({ title: '时光机' })

const { user } = useAuthSession()
const requestUrl = useRequestURL()

function timelineOrigin(): string {
  if (import.meta.server) {
    return requestUrl.origin
  }
  return window.location.origin
}

/** 公开接口只拉取 visibility=public 的记录，与账号角色无关 */
const publicHomeAlertDescription = computed(() => {
  const slug = user.value?.publicSlug?.trim()
  if (slug) {
    return `「/@${slug}」只展示可见性为「公开」的事件。新建默认是「私密」，若要出现在个人主页，请改为「公开」或在下拉里修改已有条目。「仅链接」不会在主页列出，但在本条下方会显示可复制的分享地址（/p/${slug}/t/…）。`
  }
  return '个人公开主页只展示「公开」事件。新建默认是「私密」。「仅链接」条目会在列表中显示分享链接，但需要先在「资料」中设置 public slug。'
})

type Ev = { id: number; title: string; occurredOn: string; visibility: string; shareToken?: string | null }

function timelineUnlistedShareUrl(e: Ev): string {
  if (e.visibility !== 'unlisted' || !e.shareToken?.trim()) {
    return ''
  }
  const slug = user.value?.publicSlug?.trim()
  if (!slug) {
    return ''
  }
  return `${timelineOrigin()}/p/${encodeURIComponent(slug)}/t/${encodeURIComponent(e.shareToken)}`
}

function timelineUnlistedShareBlockedReason(e: Ev): string {
  if (e.visibility !== 'unlisted') {
    return ''
  }
  if (!e.shareToken?.trim()) {
    return '分享令牌缺失，请先将可见性改为其他再改回「仅链接」重试。'
  }
  if (!user.value?.publicSlug?.trim()) {
    return '已设为仅链接，但尚未在「资料」中设置 public slug，无法生成分享地址。设置后即可得到完整链接。'
  }
  return ''
}

const visibilitySelectItems = [
  { label: '私密（仅自己，不上主页）', value: 'private' },
  { label: '公开（出现在 /@ 个人主页）', value: 'public' },
  { label: '仅链接（凭分享链接访问）', value: 'unlisted' },
] as const

const { fetchData } = useClientApi()

const events = ref<Ev[]>([])
const loading = ref(true)
const submitLoading = ref(false)
const deletingId = ref<number | null>(null)
const updatingVisibilityId = ref<number | null>(null)

const form = reactive({
  occurredOn: occurredOnToLocalInputValue(new Date()),
  title: '',
  bodyMarkdown: '',
  linkUrl: '',
  visibility: 'private',
})

async function load() {
  loading.value = true
  try {
    const { events: list } = await fetchData<{ events: Ev[] }>('/api/me/timeline')
    events.value = list
  } finally {
    loading.value = false
  }
}

onMounted(load)

async function add() {
  if (!form.title.trim()) {
    return
  }
  let occurredOnIso: string
  try {
    occurredOnIso = parseLocalDatetimeInput(form.occurredOn).toISOString()
  } catch {
    return
  }
  submitLoading.value = true
  try {
    await fetchData('/api/me/timeline', {
      method: 'POST',
      body: {
        occurredOn: occurredOnIso,
        title: form.title,
        bodyMarkdown: form.bodyMarkdown || null,
        linkUrl: form.linkUrl || null,
        visibility: form.visibility,
      },
    })
    form.title = ''
    form.bodyMarkdown = ''
    form.linkUrl = ''
    form.occurredOn = occurredOnToLocalInputValue(new Date())
    await load()
  } finally {
    submitLoading.value = false
  }
}

async function removeEvent(e: Ev) {
  if (!confirm(`确定删除「${e.title}」？此操作不可恢复。`)) {
    return
  }
  deletingId.value = e.id
  try {
    await fetchData(`/api/me/timeline/${e.id}`, { method: 'DELETE' })
    await load()
  } finally {
    deletingId.value = null
  }
}

function visibilitySelectDisabled(e: Ev) {
  if (updatingVisibilityId.value !== null && updatingVisibilityId.value !== e.id) {
    return true
  }
  if (deletingId.value !== null) {
    return true
  }
  return false
}

function deleteDisabled(e: Ev) {
  if (updatingVisibilityId.value !== null) {
    return true
  }
  if (deletingId.value !== null && deletingId.value !== e.id) {
    return true
  }
  return false
}

async function updateVisibility(e: Ev, visibility: string) {
  if (visibility === e.visibility) {
    return
  }
  updatingVisibilityId.value = e.id
  try {
    await fetchData(`/api/me/timeline/${e.id}`, {
      method: 'PUT',
      body: { visibility },
    })
    await load()
  } finally {
    updatingVisibilityId.value = null
  }
}
</script>

<template>
  <UContainer class="max-w-3xl py-8">
    <div class="space-y-6">
      <header>
        <h1 class="text-2xl font-semibold text-highlighted">
          时光机
        </h1>
        <p class="mt-1 text-sm text-muted">
          发生时间精确到秒；展示按你本机时区格式化。
        </p>
      </header>

      <UAlert
        color="neutral"
        variant="subtle"
        icon="i-lucide-info"
        title="个人主页如何展示时光机"
        :description="publicHomeAlertDescription"
      />

      <UCard class="ring-1 ring-default/60">
        <template #header>
          <span class="font-medium text-highlighted">新建事件</span>
        </template>
        <div class="space-y-5">
          <UFormField label="发生时间" name="occurredOn" required>
            <input
              v-model="form.occurredOn"
              type="datetime-local"
              step="1"
              required
              class="w-full rounded-md border border-default bg-default px-3 py-2 text-sm text-highlighted shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
            >
          </UFormField>

          <div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
            <UFormField label="标题" name="title" required class="min-w-0">
              <UInput v-model="form.title" placeholder="简短标题" class="w-full" />
            </UFormField>
            <UFormField label="链接（可选）" name="linkUrl" class="min-w-0">
              <UInput v-model="form.linkUrl" placeholder="https://…" class="w-full" />
            </UFormField>
          </div>

          <UFormField label="正文（可选）" name="bodyMarkdown">
            <UTextarea v-model="form.bodyMarkdown" placeholder="补充说明" :rows="4" class="w-full" />
          </UFormField>

          <div class="flex flex-col gap-3 border-t border-default pt-5 sm:flex-row sm:items-end sm:justify-between">
            <UFormField label="可见性" name="visibility" class="w-full sm:max-w-xs">
              <USelect
                v-model="form.visibility"
                class="w-full"
                :items="[...visibilitySelectItems]"
              />
            </UFormField>
            <UButton
              class="shrink-0 sm:self-end"
              :loading="submitLoading"
              @click="add"
            >
              添加
            </UButton>
          </div>
        </div>
      </UCard>

      <section aria-labelledby="timeline-list-heading" class="space-y-3">
        <h2 id="timeline-list-heading" class="text-sm font-medium text-muted">
          我的记录
        </h2>

        <div v-if="loading" class="text-muted">
          加载中…
        </div>
        <UEmpty
          v-else-if="!events.length"
          title="还没有事件"
          description="在上方填写发生时间与标题，添加第一条时光机记录。"
        />
        <ul v-else class="relative space-y-0">
          <li
            v-for="(e, idx) in events"
            :key="e.id"
            class="relative flex gap-3 pb-6 pl-0.5 last:pb-0 sm:gap-4"
          >
            <div
              v-if="idx < events.length - 1"
              class="absolute left-[11px] top-6 bottom-0 w-px bg-default"
              aria-hidden="true"
            />
            <div class="relative z-[1] flex shrink-0 flex-col items-center pt-1">
              <span class="size-3 rounded-full border-2 border-primary bg-default ring-4 ring-primary/15" />
            </div>
            <article
              class="min-w-0 flex-1 rounded-xl border border-default bg-gradient-to-br from-elevated/90 to-default p-4 shadow-sm transition-colors hover:border-primary/25"
            >
              <div class="flex gap-3 sm:items-start sm:justify-between">
                <div class="min-w-0 flex-1 space-y-2">
                  <time
                    class="block text-xs font-medium tabular-nums tracking-tight text-muted"
                    :datetime="occurredOnToIsoAttr(e.occurredOn)"
                  >{{ formatOccurredOnDisplay(e.occurredOn) }}</time>
                  <h3 class="text-base font-semibold leading-snug text-highlighted">
                    {{ e.title }}
                  </h3>
                </div>
                <UButton
                  icon="i-lucide-trash-2"
                  color="error"
                  variant="ghost"
                  size="sm"
                  label="删除"
                  class="shrink-0"
                  :loading="deletingId === e.id"
                  :disabled="deleteDisabled(e)"
                  @click="removeEvent(e)"
                />
              </div>
              <div class="mt-4 border-t border-default/60 pt-4">
                <UFormField label="可见性" :name="`timeline-vis-${e.id}`" class="max-w-lg">
                  <USelect
                    :model-value="e.visibility"
                    class="w-full"
                    :items="[...visibilitySelectItems]"
                    :loading="updatingVisibilityId === e.id"
                    :disabled="visibilitySelectDisabled(e)"
                    @update:model-value="(v: string) => updateVisibility(e, v)"
                  />
                </UFormField>
                <UAlert
                  v-if="timelineUnlistedShareUrl(e)"
                  class="mt-3"
                  color="neutral"
                  variant="subtle"
                  title="仅链接分享"
                  :description="timelineUnlistedShareUrl(e)"
                />
                <UAlert
                  v-else-if="e.visibility === 'unlisted' && timelineUnlistedShareBlockedReason(e)"
                  class="mt-3"
                  color="warning"
                  variant="subtle"
                  title="暂时无法生成分享链接"
                  :description="timelineUnlistedShareBlockedReason(e)"
                />
              </div>
            </article>
          </li>
        </ul>
      </section>
    </div>
  </UContainer>
</template>
