// 일정(주간 캘린더) 날짜 유틸 — 모두 'YYYY-MM-DD' 로컬 날짜 문자열 기준(시간대 이동 방지).

// 월요일 시작 요일 라벨(월~일)
export const DOW_KO = ['월', '화', '수', '목', '금', '토', '일'] as const

// Date → 로컬 'YYYY-MM-DD'
export function isoOf(date: Date): string {
  const y = date.getFullYear()
  const m = String(date.getMonth() + 1).padStart(2, '0')
  const d = String(date.getDate()).padStart(2, '0')
  return `${y}-${m}-${d}`
}

// 'YYYY-MM-DD' → 로컬 Date(자정)
export function dateOf(iso: string): Date {
  const [y, m, d] = iso.split('-').map(Number)
  return new Date(y ?? 1970, (m ?? 1) - 1, d ?? 1)
}

// 오늘(로컬) ISO
export function todayIso(): string {
  return isoOf(new Date())
}

// iso 가 속한 주의 월요일 ISO
export function mondayOf(iso: string): string {
  const dt = dateOf(iso)
  // getDay(): 0=일 … 6=토 → 월요일까지 거슬러 올라갈 일수
  const back = (dt.getDay() + 6) % 7
  dt.setDate(dt.getDate() - back)
  return isoOf(dt)
}

// iso + n일
export function addDays(iso: string, n: number): string {
  const dt = dateOf(iso)
  dt.setDate(dt.getDate() + n)
  return isoOf(dt)
}

// 요일 인덱스(0=월 … 6=일)
function dowIndex(iso: string): number {
  return (dateOf(iso).getDay() + 6) % 7
}

export interface WeekDay {
  iso: string
  dow: string
  d: number
  weekend: boolean
  isToday: boolean
}

// 주 시작(월요일) ISO → 7일 배열
export function weekDays(weekStartIso: string): WeekDay[] {
  const today = todayIso()
  return Array.from({ length: 7 }, (_, i) => {
    const iso = addDays(weekStartIso, i)
    return {
      iso,
      dow: DOW_KO[i] ?? '',
      d: dateOf(iso).getDate(),
      weekend: i >= 5,
      isToday: iso === today,
    }
  })
}

// 주 범위 라벨 — 예: '2026년 6월 22 – 28일' / 월이 다르면 '6월 29 – 7월 5일'
export function weekRangeLabel(weekStartIso: string): string {
  const s = dateOf(weekStartIso)
  const e = dateOf(addDays(weekStartIso, 6))
  const sm = s.getMonth() + 1
  const em = e.getMonth() + 1
  if (sm === em) {
    return `${s.getFullYear()}년 ${sm}월 ${s.getDate()} – ${e.getDate()}일`
  }
  return `${s.getFullYear()}년 ${sm}월 ${s.getDate()}일 – ${em}월 ${e.getDate()}일`
}

// 단일/다중일 표시용 — '6월 22일 (월)' 또는 '6월 22일(월) – 24일(수)'
export function eventDateText(start: string, end: string): string {
  const s = dateOf(start)
  if (start === end) {
    return `${s.getMonth() + 1}월 ${s.getDate()}일 (${DOW_KO[dowIndex(start)]})`
  }
  const e = dateOf(end)
  return `${s.getMonth() + 1}월 ${s.getDate()}일(${DOW_KO[dowIndex(start)]}) – ${e.getMonth() + 1}월 ${e.getDate()}일(${DOW_KO[dowIndex(end)]})`
}

// 다중일 일수(포함 양끝)
export function spanDays(start: string, end: string): number {
  return Math.round((dateOf(end).getTime() - dateOf(start).getTime()) / 86400000) + 1
}

// ===== 월간(달력 그리드) =====

// 해당 월의 1일 ISO
export function firstOfMonth(iso: string): string {
  const d = dateOf(iso)
  return isoOf(new Date(d.getFullYear(), d.getMonth(), 1))
}

// iso + n개월 (말일 넘침 보정)
export function addMonths(iso: string, n: number): string {
  const d = dateOf(iso)
  const day = d.getDate()
  const base = new Date(d.getFullYear(), d.getMonth() + n, 1)
  const dim = new Date(base.getFullYear(), base.getMonth() + 1, 0).getDate()
  base.setDate(Math.min(day, dim))
  return isoOf(base)
}

// 월 라벨 — '2026년 6월'
export function monthLabel(iso: string): string {
  const d = dateOf(iso)
  return `${d.getFullYear()}년 ${d.getMonth() + 1}월`
}

// 달력 그리드의 하루(요일 + 이번 달 여부)
export interface MonthDay extends WeekDay {
  inMonth: boolean
}

// 월 달력 그리드 — 1일이 속한 주의 월요일부터 말일이 속한 주의 일요일까지(4~6주)
export function monthGridWeeks(iso: string): MonthDay[][] {
  const monthIdx = dateOf(firstOfMonth(iso)).getMonth()
  const gridStart = mondayOf(firstOfMonth(iso))
  const first = dateOf(firstOfMonth(iso))
  const lastDayIso = isoOf(new Date(first.getFullYear(), first.getMonth() + 1, 0))
  const gridEnd = addDays(mondayOf(lastDayIso), 6)
  const today = todayIso()

  const weeks: MonthDay[][] = []
  let cur = gridStart
  while (cur <= gridEnd) {
    const week: MonthDay[] = []
    for (let i = 0; i < 7; i++) {
      const dayIso = addDays(cur, i)
      const dt = dateOf(dayIso)
      week.push({
        iso: dayIso,
        dow: DOW_KO[i] ?? '',
        d: dt.getDate(),
        weekend: i >= 5,
        isToday: dayIso === today,
        inMonth: dt.getMonth() === monthIdx,
      })
    }
    weeks.push(week)
    cur = addDays(cur, 7)
  }
  return weeks
}
