/**
 * 일정/할일 질의 컨텍스트 빌더 — "오늘 업무 목록 알려줘" 류 질문에
 * 연결된 Google Calendar(iCal 캐시) + Google Tasks 의 *실데이터*를 주입한다.
 *
 * 문제: 채팅 경로(RAG)는 두뇌·기억만 검색해서, 캘린더가 연결돼 있어도
 * "오늘 일정"을 묻면 모델이 모르거나 지어냈다. 데일리 브리핑(텔레그램)과
 * 같은 소스를 채팅에도 노출한다.
 *
 * 신뢰성 규칙: 데이터에 없는 일정·할일을 지어내지 말라는 지시를 블록에 포함.
 * 미연결이면 연결 방법을 안내하는 블록을 반환 — 모델이 환각으로 메꾸지 않게.
 */
import * as vscode from 'vscode';
import { logInfo } from '../../utils';
import { refreshCalendarCache, readCalendarEventsCache, readCalendarConfig } from '../../features/calendar/calendarCache';
import { listTasks } from '../../features/calendar/tasksApi';

const SCHEDULE_RE = /(오늘|내일|이번\s*주|금주|다음\s*주)?\s*(업무\s*목록|할\s*일|할일|일정|스케줄|미팅|회의\s*일정|투두|to-?do)|캘린더|calendar|tasks\s*목록/i;

/** 일정/할일을 묻는 질의인지. 짧은 인사·코드 질문에 오탐하지 않게 보수적으로. */
export function isScheduleRequest(prompt: string): boolean {
    const p = (prompt || '').trim();
    if (!p || p.length > 200) return false; // 긴 작업 지시문은 제외
    return SCHEDULE_RE.test(p);
}

function kstYmd(offsetDays = 0): string {
    const now = new Date(Date.now() + offsetDays * 86_400_000);
    const parts = new Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Seoul', year: 'numeric', month: '2-digit', day: '2-digit' }).format(now);
    return parts; // en-CA → YYYY-MM-DD
}

/**
 * 일정 데이터 블록 생성. 미연결/실패 시에도 모델이 정직하게 답하도록 상태를 명시.
 */
export async function buildScheduleContext(context: vscode.ExtensionContext, prompt: string): Promise<string> {
    const cfg = readCalendarConfig(context);
    if (!cfg.icalUrl && !cfg.refreshToken) {
        return [
            '[SCHEDULE DATA — Google Calendar/Tasks]',
            '상태: 캘린더가 연결되어 있지 않음.',
            '→ 사용자에게 "Astra: Google Calendar (iCal) 연결" 또는 "Astra: Google Calendar OAuth 연결 (쓰기)" 명령으로 연결하라고 안내하라. 일정을 지어내지 말 것.',
        ].join('\n');
    }

    // 질의의 기간 해석 — 기본 오늘, "내일"/"이번 주" 키워드 반영.
    const p = prompt || '';
    const wantTomorrow = /내일/.test(p);
    const wantWeek = /이번\s*주|금주|다음\s*주/.test(p);
    const startYmd = wantTomorrow ? kstYmd(1) : kstYmd(0);
    const endYmd = wantWeek ? kstYmd(7) : startYmd;
    const todayYmd = kstYmd(0);
    const rangeLabel = wantWeek ? `${startYmd} ~ ${endYmd}` : startYmd;

    const lines: string[] = [
        `[SCHEDULE DATA — Google Calendar/Tasks 실데이터 · 기준 ${rangeLabel} (KST)]`,
        '아래 데이터만 근거로 답하라. 여기에 없는 일정·할일을 지어내지 말고, 비어 있으면 "없다"고 답하라.',
    ];

    // (1) 캘린더 일정 — 캐시 새로고침 best-effort.
    try { await refreshCalendarCache(context); } catch { /* 기존 캐시 사용 */ }
    const events = readCalendarEventsCache(context)
        .filter(e => { const d = (e.startIso || '').slice(0, 10); return d >= startYmd && d <= endYmd; })
        .sort((a, b) => a.startIso.localeCompare(b.startIso));
    lines.push('', `■ 일정 (${events.length}건)`);
    for (const e of events.slice(0, 20)) {
        const d = e.startIso.slice(0, 10);
        const time = e.allDay ? '종일' : e.startIso.slice(11, 16);
        lines.push(`- ${wantWeek ? d + ' ' : ''}${time} ${e.summary}${e.location ? ` @${e.location}` : ''}`);
    }
    if (!events.length) lines.push('- (없음)');

    // (2) Google Tasks — 미완료: 기간 내 마감 + 기한 경과 + 조건부(무기한).
    const tr = await listTasks(context, { showCompleted: false, maxResults: 100 });
    if (tr.ok) {
        const open = tr.tasks.filter(t => t.status === 'needsAction');
        const inRange = open.filter(t => t.due && t.due >= startYmd && t.due <= endYmd);
        const overdue = open.filter(t => t.due && t.due < todayYmd);
        const conditional = open.filter(t => !t.due && /^\[조건부\]/.test(t.title));
        lines.push('', `■ 할 일 — 기간 내 마감 (${inRange.length}건)`);
        for (const t of inRange.slice(0, 20)) lines.push(`- ${t.due} ${t.title}`);
        if (!inRange.length) lines.push('- (없음)');
        if (overdue.length) {
            lines.push('', `■ 기한 지난 미완료 (${overdue.length}건)`);
            for (const t of overdue.slice(0, 10)) lines.push(`- ${t.due} ${t.title}`);
        }
        if (conditional.length) {
            lines.push('', `■ 조건부 대기 (${conditional.length}건)`);
            for (const t of conditional.slice(0, 10)) lines.push(`- ${t.title}`);
        }
    } else {
        lines.push('', `■ 할 일: 조회 실패 — ${tr.error}`);
        lines.push('→ 이 오류 메시지를 사용자에게 그대로 전달하라 (할일을 지어내지 말 것).');
    }

    logInfo('Schedule context 주입.', { events: events.length, range: rangeLabel, tasksOk: tr.ok });
    return lines.join('\n');
}
