import { computed, ref } from 'vue'
import { defineStore } from 'pinia'
import { useSchedule } from '@/composables/useSchedule'
import {
  addDays,
  mondayOf,
  todayIso,
  weekDays,
  weekRangeLabel,
  type WeekDay,
} from '@/shared/utils/scheduleDate'
import type {
  ApiScheduleCategory,
  ApiScheduleEvent,
  ApiSchedulePerson,
  ScheduleCategoryPayload,
  ScheduleEventPayload,
} from '@/types/schedule'

// 일정 스토어 — 카테고리/일정/참석자 + 주간 네비 상태 + CRUD
export const useScheduleStore = defineStore('schedule', () => {
  const api = useSchedule()

  const categories = ref<ApiScheduleCategory[]>([])
  const events = ref<ApiScheduleEvent[]>([])
  const people = ref<ApiSchedulePerson[]>([])
  // 활성(표시) 카테고리 id 집합 — 유형 필터
  const activeTypeIds = ref<Set<string>>(new Set())
  // 주 시작(월요일) ISO
  const weekStart = ref<string>(mondayOf(todayIso()))
  const loading = ref(false)

  // 파생: 주간 7일
  const days = computed<WeekDay[]>(() => weekDays(weekStart.value))
  const rangeLabel = computed(() => weekRangeLabel(weekStart.value))
  const weekEnd = computed(() => addDays(weekStart.value, 6))

  // 카테고리별 현재 주 일정 수(필터 드롭다운 표기용)
  const counts = computed<Record<string, number>>(() => {
    const c: Record<string, number> = {}
    for (const e of events.value) c[e.categoryId] = (c[e.categoryId] || 0) + 1
    return c
  })

  // --- 로딩 ---

  // 최초 진입 — 카테고리/참석자/주간 일정 동시 로드 + 필터 전체 활성화
  async function init(): Promise<void> {
    loading.value = true
    try {
      const [cats, ppl, evs] = await Promise.all([
        api.listCategories(),
        api.listPeople(),
        api.listEvents(weekStart.value, weekEnd.value),
      ])
      categories.value = cats
      people.value = ppl
      events.value = evs
      activeTypeIds.value = new Set(cats.map((c) => c.id))
    } finally {
      loading.value = false
    }
  }

  // 현재 주 일정만 재조회
  async function reloadEvents(): Promise<void> {
    events.value = await api.listEvents(weekStart.value, weekEnd.value)
  }

  // --- 주간 네비 ---
  function goPrevWeek(): void {
    weekStart.value = addDays(weekStart.value, -7)
    void reloadEvents()
  }
  function goNextWeek(): void {
    weekStart.value = addDays(weekStart.value, 7)
    void reloadEvents()
  }
  function goToday(): void {
    weekStart.value = mondayOf(todayIso())
    void reloadEvents()
  }

  // --- 유형 필터 ---
  function toggleType(id: string): void {
    const n = new Set(activeTypeIds.value)
    if (n.has(id)) n.delete(id)
    else n.add(id)
    activeTypeIds.value = n
  }
  function setAllTypes(on: boolean): void {
    activeTypeIds.value = on
      ? new Set(categories.value.map((c) => c.id))
      : new Set()
  }

  // --- 일정 CRUD ---
  async function createEvent(payload: ScheduleEventPayload): Promise<string> {
    const ev = await api.createEvent(payload)
    // 활성 필터에 카테고리 포함 보장
    if (!activeTypeIds.value.has(ev.categoryId)) toggleType(ev.categoryId)
    await reloadEvents()
    return ev.id
  }
  async function updateEvent(
    id: string,
    payload: Partial<ScheduleEventPayload>,
  ): Promise<void> {
    await api.updateEvent(id, payload)
    await reloadEvents()
  }
  async function deleteEvent(id: string): Promise<void> {
    await api.deleteEvent(id)
    events.value = events.value.filter((e) => e.id !== id)
  }

  // --- 카테고리 CRUD ---
  async function createCategory(
    payload: ScheduleCategoryPayload,
  ): Promise<void> {
    const cat = await api.createCategory(payload)
    categories.value = [...categories.value, cat]
    toggleTypeOn(cat.id)
  }
  async function updateCategory(
    id: string,
    payload: Partial<ScheduleCategoryPayload>,
  ): Promise<void> {
    const cat = await api.updateCategory(id, payload)
    categories.value = categories.value.map((c) => (c.id === id ? cat : c))
  }
  async function deleteCategory(id: string): Promise<void> {
    await api.deleteCategory(id)
    categories.value = categories.value.filter((c) => c.id !== id)
    const n = new Set(activeTypeIds.value)
    n.delete(id)
    activeTypeIds.value = n
    // 포함 일정이 cascade 삭제되었으므로 주간 일정 재조회
    await reloadEvents()
  }

  function toggleTypeOn(id: string): void {
    if (!activeTypeIds.value.has(id)) {
      activeTypeIds.value = new Set([...activeTypeIds.value, id])
    }
  }

  return {
    categories,
    events,
    people,
    activeTypeIds,
    weekStart,
    loading,
    days,
    rangeLabel,
    counts,
    init,
    reloadEvents,
    goPrevWeek,
    goNextWeek,
    goToday,
    toggleType,
    setAllTypes,
    createEvent,
    updateEvent,
    deleteEvent,
    createCategory,
    updateCategory,
    deleteCategory,
  }
})
