/**
 * 최근 메일 수집 공통 모듈 (v2.2.271) — /email 브리핑과 이메일 워처가 공유.
 * Outlook(받은+보낸) + Gmail(연결 시)을 MailLite 로 정규화한다.
 * 참조번호(O1../G1..)는 여기서 부여 — 호출자(핸들러)가 목록 캐시에 그대로 사용.
 */

import * as vscode from 'vscode';
import { listMessageIds, getMessage } from './gmailApi';
import { listInbox, listSent, type OutlookMail } from './outlookApi';
import type { MailLite } from './emailBrief';

export interface GmailThreadItem { threadId: string; subject: string; from: string; date: number }

export interface CollectResult {
    inbox: MailLite[];
    sent: MailLite[];
    /** O 참조번호 순서 그대로의 Outlook 원본 (목록 캐시용). */
    outlookMails: OutlookMail[];
    /** G 참조번호 순서 그대로의 Gmail 스레드 (목록 캐시용). */
    gmailItems: GmailThreadItem[];
    outlookError?: string;
    gmailError?: string;
}

const fmtDate = (ms: number) => new Date(ms).toISOString().slice(0, 16).replace('T', ' ');

/** 프로바이더 on/off (v2.2.276) — 끄면 수집 시도 자체를 안 해 채팅에 오류성 문구가 없다. */
export function emailProviders(): { outlook: boolean; gmail: boolean } {
    const cfg = vscode.workspace.getConfiguration('g1nation');
    return {
        outlook: cfg.get<boolean>('email.outlookEnabled', true) !== false,
        gmail: cfg.get<boolean>('email.gmailEnabled', true) !== false,
    };
}

export async function collectRecentMails(
    days: number,
    context?: vscode.ExtensionContext,
    opts: { gmailThreads?: number; outlookMax?: number; sentMax?: number } = {},
): Promise<CollectResult> {
    const out: CollectResult = { inbox: [], sent: [], outlookMails: [], gmailItems: [] };
    const providers = emailProviders();

    // Outlook — 받은편지함(+하위 폴더) + 보낸편지함 (답변 여부 판정용). 비활성 시 조용히 스킵.
    const includeSub = vscode.workspace.getConfiguration('g1nation').get<boolean>('email.includeSubfolders', true) !== false;
    const [inR, sentR] = providers.outlook
        ? await Promise.all([
            listInbox(days, opts.outlookMax ?? 40, includeSub),
            listSent(days, opts.sentMax ?? 100),
        ])
        : [{ ok: true as const, data: [] }, { ok: true as const, data: [] }];
    if (inR.ok) {
        out.outlookMails = inR.data;
        inR.data.forEach((m, i) => out.inbox.push({
            ref: `O${i + 1}`, entryId: m.entryId, subject: m.subject, from: m.from,
            received: m.received, unread: m.unread, snippet: m.snippet, ccOnly: m.ccOnly,
        }));
        if (sentR.ok) sentR.data.forEach(m => out.sent.push({
            subject: m.subject, from: '나', to: m.to, received: m.received, outgoing: true,
        }));
    } else {
        out.outlookError = inR.error;
    }

    // Gmail — 활성 + 연결돼 있으면 스레드 병합 (SENT 라벨 = 내 발신). 비활성 시 조용히 스킵.
    if (context && providers.gmail) {
        const maxThreads = Math.max(1, Math.min(20, opts.gmailThreads ?? 12));
        const ids = await listMessageIds(context, {
            query: `newer_than:${days}d -in:spam -in:trash -category:promotions -category:social`,
            maxResults: 40,
        });
        if (ids.ok) {
            const seen = new Set<string>();
            const firstOfThread: string[] = [];
            for (const m of ids.data) {
                if (!m.threadId || seen.has(m.threadId)) continue;
                seen.add(m.threadId);
                firstOfThread.push(m.id);
                if (firstOfThread.length >= maxThreads) break;
            }
            for (const id of firstOfThread) {
                const r = await getMessage(context, id);
                if (!r.ok) continue;
                const isSent = r.data.labels.includes('SENT');
                const lite: MailLite = {
                    subject: r.data.subject || '(제목 없음)', from: isSent ? '나' : r.data.from,
                    received: fmtDate(r.data.date), snippet: r.data.snippet, outgoing: isSent,
                };
                if (isSent) { out.sent.push(lite); continue; }
                out.gmailItems.push({ threadId: r.data.threadId, subject: lite.subject, from: r.data.from, date: r.data.date });
                lite.ref = `G${out.gmailItems.length}`;
                out.inbox.push(lite);
            }
        } else {
            out.gmailError = ids.error;
        }
    }

    return out;
}
