/**
 * Schedule Conflict Check — 일정 생성 전 기존 일정과의 겹침 감지.
 *
 * Self-Evolving OS 마스터 플랜 병렬 트랙 6-2 + 6-3. Requirement Graph 의
 * 일정 필수 요소 "충돌 확인" 과 Constitution "승인 없는 외부 액션 금지" 의
 * 실행 계층:
 *   - 에이전트가 <create_calendar_event> 로 일정을 만들기 *전에* ICS 캐시와
 *     비교해 겹침을 감지
 *   - 충돌 시 생성을 *차단*하고 사용자 확인을 요청 (force="true" 명시 시에만 강행)
 *
 * 순수 모듈 — vscode/네트워크 의존 없음. 캐시 공급은 calendarCache, 차단 배선은
 * agent/actions/calendar.ts 담당.
 */

export interface CachedCalEvent {
    summary: string;
    /** ISO 문자열 (toISOString 또는 로컬 'YYYY-MM-DDTHH:MM'). */
    startIso: string;
    /** 없으면 1시간으로 간주. */
    endIso?: string;
    allDay: boolean;
    location?: string;
}

export interface CandidateEvent {
    startIso: string;
    endIso?: string;
    /** endIso 없을 때 사용. 기본 60분. */
    durationMinutes?: number;
    allDay?: boolean;
}

const HOUR_MS = 3600000;
const DAY_MS = 86400000;

function parseIso(iso: string): number | null {
    const t = Date.parse(iso);
    return isNaN(t) ? null : t;
}

/** [start, end) 구간 계산. all-day 는 해당 날짜 00:00~다음날 00:00 (로컬). */
function rangeOf(startIso: string, endIso: string | undefined, durationMinutes: number | undefined, allDay: boolean): [number, number] | null {
    const start = parseIso(startIso);
    if (start === null) return null;
    if (allDay) {
        const d = new Date(start);
        const dayStart = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
        return [dayStart, dayStart + DAY_MS];
    }
    let end: number | null = endIso ? parseIso(endIso) : null;
    if (end === null) end = start + (durationMinutes && durationMinutes > 0 ? durationMinutes * 60000 : HOUR_MS);
    if (end <= start) end = start + HOUR_MS; // 역전 입력 방어
    return [start, end];
}

/**
 * 후보 일정과 겹치는 기존 일정 반환. 파싱 불가능한 입력은 보수적으로 *충돌 없음*
 * 처리 (잘못된 날짜로 생성 자체가 실패할 것이므로 여기서 막지 않는다).
 */
export function findScheduleConflicts(existing: CachedCalEvent[], candidate: CandidateEvent): CachedCalEvent[] {
    const cand = rangeOf(candidate.startIso, candidate.endIso, candidate.durationMinutes, candidate.allDay === true);
    if (!cand) return [];
    const [cs, ce] = cand;
    const out: CachedCalEvent[] = [];
    for (const ev of existing || []) {
        const r = rangeOf(ev.startIso, ev.endIso, undefined, ev.allDay);
        if (!r) continue;
        const [es, ee] = r;
        if (cs < ee && es < ce) out.push(ev); // 구간 겹침
    }
    return out;
}

/** 충돌 보고 텍스트 — 액션 리포트·에이전트 internal 메시지 공용. */
export function formatConflictReport(conflicts: CachedCalEvent[]): string {
    const lines = conflicts.slice(0, 5).map((c) => {
        const when = c.allDay ? `${c.startIso.slice(0, 10)} (종일)` : c.startIso.replace('T', ' ').slice(0, 16);
        return `- ${c.summary} · ${when}${c.location ? ` · ${c.location}` : ''}`;
    });
    return `기존 일정과 겹칩니다:\n${lines.join('\n')}\n생성을 보류했습니다. 그래도 진행하려면 사용자 확인 후 force="true" 로 다시 시도하세요.`;
}
