import { computed, ref } from 'vue'
import { defineStore } from 'pinia'
import { useSchedule } from '@/composables/useSchedule'
import { useAuthStore } from './auth.store'
import {
  addDays,
  addMonths,
  firstOfMonth,
  mondayOf,
  monthGridWeeks,
  monthLabel,
  todayIso,
  weekDays,
  weekRangeLabel,
  type MonthDay,
  type WeekDay,
} from '@/shared/utils/scheduleDate'
import type {
  ApiScheduleCategory,
  ApiScheduleEvent,
  ApiSchedulePerson,
  ScheduleCategoryPayload,
  ScheduleEventPayload,
} from '@/types/schedule'

export type ScheduleViewMode = 'week' | 'month'

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

  const categories = ref<ApiScheduleCategory[]>([])
  const events = ref<ApiScheduleEvent[]>([])
  const people = ref<ApiSchedulePerson[]>([])
  // 활성(표시) 카테고리 id 집합 — 유형 필터
  const activeTypeIds = ref<Set<string>>(new Set())
  // '내 일정만' 보기 — 참석자/전직원/작성자 기준
  const mineOnly = ref(false)
  // 보기 모드(주간/월간) + 기준 날짜(이 날짜가 속한 주/월을 표시)
  const viewMode = ref<ScheduleViewMode>('week')
  const anchor = ref<string>(todayIso())
  const loading = ref(false)

  // --- 파생: 표시 단위 ---
  // 주간: 월요일 시작 7일
  const weekStart = computed(() => mondayOf(anchor.value))
  const days = computed<WeekDay[]>(() => weekDays(weekStart.value))
  // 월간: 달력 그리드(주 배열)
  const monthWeeks = computed<MonthDay[][]>(() => monthGridWeeks(anchor.value))

  // 조회 범위(현재 모드가 화면에 보여주는 전체 기간)
  const rangeStart = computed(() => {
    if (viewMode.value === 'week') return weekStart.value
    const w = monthWeeks.value
    return w[0]?.[0]?.iso ?? weekStart.value
  })
  const rangeEnd = computed(() => {
    if (viewMode.value === 'week') return addDays(weekStart.value, 6)
    const w = monthWeeks.value
    return w[w.length - 1]?.[6]?.iso ?? addDays(weekStart.value, 6)
  })

  // 상단 범위 라벨 — 주간: '2026년 6월 23 – 29일' / 월간: '2026년 6월'
  const rangeLabel = computed(() =>
    viewMode.value === 'week'
      ? weekRangeLabel(weekStart.value)
      : monthLabel(anchor.value),
  )

  // '내 일정' 판정 — 참석자 기준(전 직원 대상은 전원 포함이므로 내 일정에 포함)
  const myId = computed(() => authStore.user?.id ?? null)
  function isMine(e: ApiScheduleEvent): boolean {
    if (!myId.value) return false
    return e.allHands || e.attendees.some((a) => a.id === myId.value)
  }
  // 화면 표시 대상 일정 — '내 일정만' 토글 적용(카테고리 필터는 뷰 컴포넌트가 처리)
  const displayEvents = computed(() =>
    mineOnly.value ? events.value.filter(isMine) : events.value,
  )

  // 카테고리별 현재 범위 일정 수(필터 드롭다운 표기용) — 표시 대상 기준
  const counts = computed<Record<string, number>>(() => {
    const c: Record<string, number> = {}
    for (const e of displayEvents.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(rangeStart.value, rangeEnd.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(rangeStart.value, rangeEnd.value)
  }

  // --- 네비(모드별) ---
  function setViewMode(mode: ScheduleViewMode): void {
    if (viewMode.value === mode) return
    viewMode.value = mode
    void reloadEvents()
  }
  function goPrev(): void {
    anchor.value =
      viewMode.value === 'week'
        ? addDays(anchor.value, -7)
        : addMonths(firstOfMonth(anchor.value), -1)
    void reloadEvents()
  }
  function goNext(): void {
    anchor.value =
      viewMode.value === 'week'
        ? addDays(anchor.value, 7)
        : addMonths(firstOfMonth(anchor.value), 1)
    void reloadEvents()
  }
  function goToday(): void {
    anchor.value = 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()
  }
  function toggleMineOnly(): void {
    mineOnly.value = !mineOnly.value
  }

  // --- 일정 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,
    displayEvents,
    people,
    activeTypeIds,
    mineOnly,
    viewMode,
    weekStart,
    loading,
    days,
    monthWeeks,
    rangeLabel,
    counts,
    init,
    reloadEvents,
    setViewMode,
    goPrev,
    goNext,
    goToday,
    toggleType,
    setAllTypes,
    toggleMineOnly,
    createEvent,
    updateEvent,
    deleteEvent,
    createCategory,
    updateCategory,
    deleteCategory,
  }
})
