/**
 * 쿼리 캐시 유틸리티
 *
 * Firestore query_cache 컬렉션을 사용하여 동일 쿼리 결과를 캐싱합니다.
 * 캐시 키: SHA-256(query) + productId + version(effectiveDate)
 * TTL: 24시간 (Firestore TTL 정책으로 자동 삭제)
 */

import { getFirestore, Timestamp, FieldValue } from 'firebase-admin/firestore';
import * as crypto from 'crypto';

const COLLECTION = 'query_cache';
const TTL_HOURS = 24;

interface CachedResult {
    result: string;
    citations?: string[];
    confidenceScore?: number;
    createdAt: Timestamp;
}

/**
 * 쿼리 문자열의 SHA-256 해시를 생성합니다.
 */
function hashQuery(query: string): string {
    return crypto.createHash('sha256').update(query.trim().toLowerCase()).digest('hex').slice(0, 16);
}

/**
 * 캐시 키를 생성합니다.
 * @param query - 원본 쿼리 문자열
 * @param productId - 상품 ID
 * @param version - 약관 버전 (effectiveDate, "YYYY-MM" 형식)
 */
export function getCacheKey(query: string, productId: string, version: string): string {
    const qHash = hashQuery(query);
    return `${qHash}_${productId}_${version}`;
}

/**
 * 캐시에서 결과를 조회합니다.
 * TTL 만료된 항목은 null을 반환합니다.
 */
export async function getFromCache(
    query: string,
    productId: string,
    version: string
): Promise<CachedResult | null> {
    const db = getFirestore();
    const key = getCacheKey(query, productId, version);
    const doc = await db.collection(COLLECTION).doc(key).get();

    if (!doc.exists) return null;

    const data = doc.data()!;
    const expireAt = data.expireAt as Timestamp;

    // TTL 확인 (Firestore TTL이 지연될 수 있으므로 앱 레벨에서도 체크)
    if (expireAt.toMillis() < Date.now()) return null;

    return {
        result: data.result,
        citations: data.citations,
        confidenceScore: data.confidenceScore,
        createdAt: data.createdAt,
    };
}

/**
 * 쿼리 결과를 캐시에 저장합니다.
 */
export async function setToCache(
    query: string,
    productId: string,
    version: string,
    result: string,
    options?: { citations?: string[]; confidenceScore?: number }
): Promise<void> {
    const db = getFirestore();
    const key = getCacheKey(query, productId, version);
    const expireAt = Timestamp.fromMillis(Date.now() + TTL_HOURS * 60 * 60 * 1000);

    await db.collection(COLLECTION).doc(key).set({
        queryHash: hashQuery(query),
        productId,
        version,
        query: query.trim(),
        result,
        citations: options?.citations ?? [],
        confidenceScore: options?.confidenceScore ?? null,
        createdAt: FieldValue.serverTimestamp(),
        expireAt,
    });
}

/**
 * 특정 상품의 캐시를 무효화합니다.
 * 재인덱싱 시 호출하여 오래된 캐시를 제거합니다.
 */
export async function invalidateCache(productId: string): Promise<number> {
    const db = getFirestore();
    const snapshot = await db.collection(COLLECTION)
        .where('productId', '==', productId)
        .get();

    if (snapshot.empty) return 0;

    const batch = db.batch();
    snapshot.docs.forEach(doc => batch.delete(doc.ref));
    await batch.commit();

    return snapshot.size;
}
