import type { CalendarWeek, CalendarEntry } from '@/features/plan/types/plan';

/**
 * 주어진 연도와 ISO 주차 번호에 해당하는 월요일 날짜를 반환.
 * 주차 1 = 해당 연도의 첫 번째 목요일이 포함된 주 (ISO 8601).
 */
function isoWeekToDate(year: number, week: number, dayOffset: number): Date {
  // 1월 4일은 항상 1주차에 포함
  const jan4 = new Date(year, 0, 4);
  const dayOfWeek = jan4.getDay() || 7; // Sun=0을 7로 변환
  const monday = new Date(jan4);
  monday.setDate(jan4.getDate() - (dayOfWeek - 1) + (week - 1) * 7);
  monday.setDate(monday.getDate() + dayOffset);
  return monday;
}

function formatICSDate(date: Date): string {
  const pad = (n: number) => String(n).padStart(2, '0');
  return (
    `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}` +
    `T${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`
  );
}

function escapeICS(str: string): string {
  return str
    .replace(/\\/g, '\\\\')
    .replace(/;/g, '\\;')
    .replace(/,/g, '\\,')
    .replace(/\n/g, '\\n');
}

function buildVEvent(
  entry: CalendarEntry,
  weekNumber: number,
  year: number,
  uid: string,
): string {
  const startDate = isoWeekToDate(year, weekNumber, entry.dayOfWeek);
  // 종일 이벤트: DTSTART는 DATE만, DTEND는 다음 날
  const endDate = new Date(startDate);
  endDate.setDate(endDate.getDate() + 1);

  const formatDate = (d: Date) => {
    const pad = (n: number) => String(n).padStart(2, '0');
    return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}`;
  };

  const lines = [
    'BEGIN:VEVENT',
    `UID:${uid}`,
    `DTSTAMP:${formatICSDate(new Date())}Z`,
    `DTSTART;VALUE=DATE:${formatDate(startDate)}`,
    `DTEND;VALUE=DATE:${formatDate(endDate)}`,
    `SUMMARY:${escapeICS(`[${entry.channel}] ${entry.title}`)}`,
    entry.description ? `DESCRIPTION:${escapeICS(entry.description)}` : null,
    `CATEGORIES:${escapeICS(entry.contentType.toUpperCase())}`,
    `STATUS:${entry.status === 'published' ? 'CONFIRMED' : entry.status === 'approved' ? 'TENTATIVE' : 'NEEDS-ACTION'}`,
    'END:VEVENT',
  ].filter(Boolean) as string[];

  return lines.join('\r\n');
}

export function exportCalendarToICS(
  weeks: CalendarWeek[],
  calendarName = 'INFINITH 콘텐츠 캘린더',
): void {
  const year = new Date().getFullYear();

  const vEvents = weeks.flatMap((week) =>
    week.entries.map((entry, idx) =>
      buildVEvent(
        entry,
        week.weekNumber,
        year,
        `infinith-${week.weekNumber}-${entry.id ?? idx}@infinith.ai`,
      ),
    ),
  );

  const icsContent = [
    'BEGIN:VCALENDAR',
    'VERSION:2.0',
    'PRODID:-//INFINITH//Marketing Content Calendar//KO',
    `X-WR-CALNAME:${escapeICS(calendarName)}`,
    'X-WR-TIMEZONE:Asia/Seoul',
    'CALSCALE:GREGORIAN',
    'METHOD:PUBLISH',
    ...vEvents,
    'END:VCALENDAR',
  ].join('\r\n');

  const blob = new Blob([icsContent], { type: 'text/calendar;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'infinith-content-calendar.ics';
  a.click();
  URL.revokeObjectURL(url);
}
