<script setup lang="ts">
// 일정 — 전사 공유 주간 타임라인(간트형) 캘린더
import { computed, onMounted, ref } from 'vue'
import AppShell from '@/layouts/AppShell.vue'
import ScheduleTimeline from '@/components/schedule/ScheduleTimeline.vue'
import ScheduleDetailPanel from '@/components/schedule/ScheduleDetailPanel.vue'
import ScheduleEventModal from '@/components/schedule/ScheduleEventModal.vue'
import ScheduleCategoryModal from '@/components/schedule/ScheduleCategoryModal.vue'
import ScheduleTypeFilter from '@/components/schedule/ScheduleTypeFilter.vue'
import { useScheduleStore } from '@/stores/schedule.store'
import { useDialogStore } from '@/stores/dialog.store'
import type {
  ApiScheduleEvent,
  ScheduleCategoryPayload,
  ScheduleEventPayload,
} from '@/types/schedule'

const store = useScheduleStore()
const dialog = useDialogStore()

const selId = ref<string | null>(null)
const eventModal = ref<{ init: ApiScheduleEvent | null } | null>(null)
const catModal = ref<{ init: import('@/types/schedule').ApiScheduleCategory | null } | null>(null)

onMounted(() => {
  void store.init().catch(() => {
    // 인터셉터가 에러 토스트 처리
  })
})

// 선택 일정 — 활성 유형 + 현재 주에 보이는 것만
const selEvent = computed<ApiScheduleEvent | null>(() => {
  const ev = store.events.find((e) => e.id === selId.value)
  if (!ev) return null
  return store.activeTypeIds.has(ev.categoryId) ? ev : null
})
const selCategory = computed(
  () => store.categories.find((c) => c.id === selEvent.value?.categoryId) ?? null,
)

// 새 일정 기본 날짜 — 보고 있는 주의 월요일
const defaultDate = computed(() => store.weekStart)

// ----- 일정 -----
function openNewEvent(): void {
  eventModal.value = { init: null }
}
function openEditEvent(ev: ApiScheduleEvent): void {
  eventModal.value = { init: ev }
}
async function onSaveEvent(payload: ScheduleEventPayload): Promise<void> {
  const init = eventModal.value?.init
  if (init) {
    await store.updateEvent(init.id, payload)
    selId.value = init.id
  } else {
    selId.value = await store.createEvent(payload)
  }
  eventModal.value = null
}
async function onDeleteEvent(ev: ApiScheduleEvent): Promise<void> {
  const ok = await dialog.confirm(
    `'${ev.title}' 일정을 삭제할까요? 이 작업은 되돌릴 수 없습니다.`,
    { title: '일정 삭제', confirmText: '삭제', variant: 'danger' },
  )
  if (!ok) return
  await store.deleteEvent(ev.id)
  if (selId.value === ev.id) selId.value = null
}

// ----- 카테고리 -----
function openNewCategory(): void {
  catModal.value = { init: null }
}
function openEditCategory(id: string): void {
  catModal.value = { init: store.categories.find((c) => c.id === id) ?? null }
}
async function onSaveCategory(payload: ScheduleCategoryPayload): Promise<void> {
  const init = catModal.value?.init
  if (init) await store.updateCategory(init.id, payload)
  else await store.createCategory(payload)
  catModal.value = null
}
async function onDeleteCategory(id: string): Promise<void> {
  const cat = store.categories.find((c) => c.id === id)
  if (!cat) return
  const cnt = store.counts[id] || 0
  const msg = cnt
    ? `'${cat.label}' 카테고리와 이번 주에 표시된 일정 ${cnt}건을 포함해 해당 카테고리의 모든 일정이 삭제됩니다. 계속할까요?`
    : `'${cat.label}' 카테고리를 삭제할까요?`
  const ok = await dialog.confirm(msg, {
    title: '카테고리 삭제',
    confirmText: '삭제',
    variant: 'danger',
  })
  if (!ok) return
  await store.deleteCategory(id)
}
</script>

<template>
  <AppShell>
    <div class="sched">
      <!-- 툴바 -->
      <div class="toolbar">
        <div class="datenav">
          <div class="navgroup">
            <button
              class="navbtn"
              title="이전 주"
              @click="store.goPrevWeek()"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              ><path d="m15 18-6-6 6-6" /></svg>
            </button>
            <button
              class="navbtn"
              title="다음 주"
              @click="store.goNextWeek()"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              ><path d="m9 18 6-6-6-6" /></svg>
            </button>
          </div>
          <span class="range">{{ store.rangeLabel }}</span>
        </div>
        <div class="spacer" />
        <ScheduleTypeFilter
          :categories="store.categories"
          :counts="store.counts"
          :active-type-ids="store.activeTypeIds"
          @toggle="store.toggleType"
          @set-all="store.setAllTypes"
          @add="openNewCategory"
          @edit="openEditCategory"
          @delete="onDeleteCategory"
        />
        <button
          class="btn primary"
          @click="openNewEvent"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2.2"
            stroke-linecap="round"
            stroke-linejoin="round"
          ><path d="M5 12h14M12 5v14" /></svg>새 일정
        </button>
      </div>

      <!-- 콘텐츠 + 상세 패널 -->
      <div class="content-row">
        <div class="viewport">
          <ScheduleTimeline
            :categories="store.categories"
            :events="store.events"
            :days="store.days"
            :active-type-ids="store.activeTypeIds"
            :sel-id="selId"
            @select="selId = $event"
            @add-category="openNewCategory"
          />
        </div>
        <div
          v-if="selEvent"
          class="detail-backdrop"
          @click="selId = null"
        />
        <ScheduleDetailPanel
          :event="selEvent"
          :category="selCategory"
          @close="selId = null"
          @edit="openEditEvent"
          @delete="onDeleteEvent"
        />
      </div>
    </div>

    <ScheduleEventModal
      v-if="eventModal"
      :categories="store.categories"
      :people="store.people"
      :init="eventModal.init"
      :default-date="defaultDate"
      @save="onSaveEvent"
      @close="eventModal = null"
    />
    <ScheduleCategoryModal
      v-if="catModal"
      :init="catModal.init"
      @save="onSaveCategory"
      @close="catModal = null"
    />
  </AppShell>
</template>

<style scoped>
/* 상단 topbar(3.25rem) 아래 영역을 가득 채우는 풀-하이트 레이아웃 */
.sched {
  height: calc(100vh - 3.25rem);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
}
.toolbar {
  display: flex;
  align-items: center;
  /* 프로젝트 목록 등 전역 .toolbar 와 동일한 컨트롤 간격 */
  gap: 0.625rem;
  /* 가로 여백은 .page(0 1.5rem)·콘텐츠 영역과 동일하게 1.5rem */
  padding: 0.6875rem 1.5rem;
  /* 전역 .toolbar 의 margin-bottom(0.875rem) 상속 차단 — 고정 바라 여분 마진 불필요 */
  margin-bottom: 0;
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
.datenav {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.datenav .range {
  font-size: 0.969rem;
  font-weight: 700;
  letter-spacing: -0.01875rem;
  white-space: nowrap;
  margin: 0 0.375rem;
}
.navgroup {
  display: flex;
}
.navgroup .navbtn:first-child {
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
.navgroup .navbtn:last-child {
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  margin-left: -1px;
}
.navbtn {
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--border-strong);
  background: #fff;
  color: var(--text-2);
  display: grid;
  place-items: center;
  cursor: pointer;
}
.navbtn:hover {
  background: #f7f8fa;
  color: var(--text);
  z-index: 1;
}
.navbtn svg {
  width: 1rem;
  height: 1rem;
}
.spacer {
  flex: 1;
}
/* '새 일정' 버튼은 전역 .btn / .btn.primary 표준(다른 화면의 주요 버튼과 동일)을 그대로 사용 */
.content-row {
  flex: 1;
  min-height: 0;
  display: flex;
  background: var(--bg);
  position: relative;
  overflow: hidden;
}
.viewport {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  display: flex;
  /* 콘텐츠 영역 상하좌우 여백 통일(1.5rem) — 툴바 가로 여백·.page 와 일치 */
  padding: 1.5rem;
}
.detail-backdrop {
  position: absolute;
  inset: 0;
  z-index: 25;
  background: rgba(20, 24, 33, 0.22);
  opacity: 0;
  animation: bd-in 0.22s ease forwards;
}
@keyframes bd-in {
  to {
    opacity: 1;
  }
}
</style>
