/**
 * links 컬렉션 → outgoingLinks/outgoingLinkIds 마이그레이션 스크립트
 *
 * links 컬렉션에 저장된 AI 추천 연결 데이터를 해당 소스 문서의
 * outgoingLinks / outgoingLinkIds 필드로 마이그레이션합니다.
 *
 * 사용법:
 *   npx ts-node --project scripts/tsconfig.json scripts/migrate-links-to-outgoing.ts           # 실제 실행
 *   npx ts-node --project scripts/tsconfig.json scripts/migrate-links-to-outgoing.ts --dry-run # dry-run 모드
 *
 * task-1747.1: links → outgoingLinks 마이그레이션
 * 생성일: 2026-04-12
 */

import * as admin from 'firebase-admin';
import * as path from 'path';
import * as fs from 'fs';

// ============================================================
// Firebase Admin 초기화
// ============================================================
if (!admin.apps.length) {
    const localKeyPath = path.resolve(__dirname, '../temp.j2h/insuwiki-j2h-902be7d0b6f5.json');
    if (fs.existsSync(localKeyPath)) {
        try {
            const serviceAccount = JSON.parse(fs.readFileSync(localKeyPath, 'utf8'));
            admin.initializeApp({
                credential: admin.credential.cert(serviceAccount),
                projectId: 'insuwiki-j2h',
            });
        } catch {
            admin.initializeApp();
            console.warn('⚠️ 서비스 계정 키 파싱 실패 — 기본 인증 사용');
        }
    } else {
        admin.initializeApp();
        console.log('ℹ️ 서비스 계정 키 없음 — 기본 인증 사용 (gcloud auth)');
    }
}

const db = admin.firestore();

// ============================================================
// 타입 정의
// ============================================================
interface LinkDocument {
    sourceDocId: string;
    sourceTitle: string;
    targetDocId: string;
    targetTitle: string;
    method: 'manual' | 'static' | 'embedding' | 'semantic';
    confidence: number;
    createdBy: 'user' | 'system' | 'ai';
    status: 'active' | 'pending';
    createdAt: admin.firestore.Timestamp;
    updatedAt?: admin.firestore.Timestamp;
    migrated?: boolean;
}

// ============================================================
// 상수
// ============================================================
const BATCH_SIZE = 500;
const LINKS_COLLECTION = 'links';
const DOCUMENTS_COLLECTION = 'documents';

// ============================================================
// 결과 집계
// ============================================================
interface MigrationStats {
    total: number;
    success: number;
    failed: number;
    skipped: number;
}

// ============================================================
// 메인 로직
// ============================================================
async function migrateLinksToOutgoing(dryRun: boolean): Promise<void> {
    console.log(`\n${'='.repeat(60)}`);
    console.log(`links → outgoingLinks 마이그레이션 시작 (${dryRun ? 'DRY-RUN 모드' : '실제 실행 모드'})`);
    console.log(`${'='.repeat(60)}\n`);

    const snapshot = await db.collection(LINKS_COLLECTION).get();
    const totalDocs = snapshot.size;

    console.log(`📋 총 ${totalDocs}개 links 문서 조회됨\n`);

    if (totalDocs === 0) {
        console.log('✅ 처리할 문서가 없습니다.');
        return;
    }

    const stats: MigrationStats = {
        total: totalDocs,
        success: 0,
        failed: 0,
        skipped: 0,
    };

    // 처리 대상 분류
    const docsToMigrate: admin.firestore.QueryDocumentSnapshot[] = [];

    snapshot.forEach(doc => {
        const data = doc.data() as LinkDocument;

        // 이미 마이그레이션된 문서 스킵
        if (data.migrated === true) {
            stats.skipped++;
            return;
        }

        // status가 'active'인 문서만 마이그레이션
        if (data.status !== 'active') {
            console.log(`  ⏭️  스킵 (pending): ${doc.id} — "${data.sourceTitle}" → "${data.targetTitle}"`);
            stats.skipped++;
            return;
        }

        docsToMigrate.push(doc);
    });

    console.log(`🔍 마이그레이션 대상: ${docsToMigrate.length}개`);
    console.log(`   스킵(이미 migrated 또는 pending): ${stats.skipped}개\n`);

    if (docsToMigrate.length === 0) {
        console.log('✅ 마이그레이션할 문서가 없습니다.');
        printSummary(stats, dryRun);
        return;
    }

    // 소스 문서 존재 여부 사전 확인 (배치 단위로 처리)
    // Firestore는 in 쿼리가 30개 제한이므로 개별 확인
    const sourceDocIds = [...new Set(docsToMigrate.map(doc => (doc.data() as LinkDocument).sourceDocId))];
    console.log(`🔎 소스 문서 존재 여부 확인 중... (고유 소스 문서: ${sourceDocIds.length}개)`);

    const existingSourceDocIds = new Set<string>();
    // 10개씩 병렬 확인
    const CHECK_CHUNK = 10;
    for (let i = 0; i < sourceDocIds.length; i += CHECK_CHUNK) {
        const chunk = sourceDocIds.slice(i, i + CHECK_CHUNK);
        const checks = await Promise.all(
            chunk.map(id => db.collection(DOCUMENTS_COLLECTION).doc(id).get())
        );
        checks.forEach(docSnap => {
            if (docSnap.exists) {
                existingSourceDocIds.add(docSnap.id);
            } else {
                console.log(`  ⚠️  소스 문서 없음, 스킵: documents/${docSnap.id}`);
            }
        });
    }

    console.log(`   존재하는 소스 문서: ${existingSourceDocIds.size}개\n`);

    // 소스 문서가 없는 link는 스킵
    const validDocs = docsToMigrate.filter(doc => {
        const data = doc.data() as LinkDocument;
        if (!existingSourceDocIds.has(data.sourceDocId)) {
            stats.skipped++;
            return false;
        }
        return true;
    });

    console.log(`✅ 실제 마이그레이션 처리 대상: ${validDocs.length}개\n`);

    if (validDocs.length === 0) {
        console.log('✅ 마이그레이션할 유효한 문서가 없습니다.');
        printSummary(stats, dryRun);
        return;
    }

    // 배치 처리
    // 각 link 문서에 대해 두 가지 작업이 필요:
    //   1. documents/{sourceDocId} 업데이트 (outgoingLinks, outgoingLinkIds arrayUnion)
    //   2. links/{linkDocId} 업데이트 (migrated: true 마킹)
    // 하나의 link가 두 개의 write를 생성하므로 배치당 처리 가능한 link 수는 250개
    const LINKS_PER_BATCH = Math.floor(BATCH_SIZE / 2); // 250

    let batchNumber = 0;

    for (let i = 0; i < validDocs.length; i += LINKS_PER_BATCH) {
        const chunk = validDocs.slice(i, i + LINKS_PER_BATCH);
        batchNumber++;

        if (dryRun) {
            console.log(`[DRY-RUN] 배치 ${batchNumber}: ${chunk.length}개 link 처리 예정`);
            chunk.slice(0, 5).forEach(doc => {
                const data = doc.data() as LinkDocument;
                console.log(
                    `  - ${doc.id}: documents/${data.sourceDocId}.outgoingLinks += "${data.targetTitle}", outgoingLinkIds += "${data.targetDocId}"`
                );
            });
            if (chunk.length > 5) {
                console.log(`  ... 외 ${chunk.length - 5}개`);
            }
            stats.success += chunk.length;
        } else {
            const batch = db.batch();

            for (const doc of chunk) {
                const data = doc.data() as LinkDocument;

                // 1. 소스 문서에 outgoingLinks / outgoingLinkIds arrayUnion
                const sourceDocRef = db.collection(DOCUMENTS_COLLECTION).doc(data.sourceDocId);
                batch.update(sourceDocRef, {
                    outgoingLinks: admin.firestore.FieldValue.arrayUnion(data.targetTitle),
                    outgoingLinkIds: admin.firestore.FieldValue.arrayUnion(data.targetDocId),
                    updatedAt: admin.firestore.FieldValue.serverTimestamp(),
                });

                // 2. link 문서에 migrated: true 마킹
                batch.update(doc.ref, {
                    migrated: true,
                    updatedAt: admin.firestore.FieldValue.serverTimestamp(),
                });
            }

            try {
                await batch.commit();
                console.log(`✅ 배치 ${batchNumber}: ${chunk.length}개 link 마이그레이션 완료`);
                stats.success += chunk.length;
            } catch (err) {
                console.error(`❌ 배치 ${batchNumber} 실패:`, err);
                stats.failed += chunk.length;
            }
        }
    }

    printSummary(stats, dryRun, batchNumber);
}

// ============================================================
// 결과 출력
// ============================================================
function printSummary(stats: MigrationStats, dryRun: boolean, batchCount?: number): void {
    console.log(`\n${'='.repeat(60)}`);
    console.log('📊 마이그레이션 결과 요약');
    console.log(`${'='.repeat(60)}`);
    console.log(`  총 처리 건수  : ${stats.total}개`);
    console.log(`  성공          : ${stats.success}개`);
    console.log(`  실패          : ${stats.failed}개`);
    console.log(`  스킵          : ${stats.skipped}개 (이미 migrated / pending / 소스 없음)`);
    if (batchCount !== undefined) {
        console.log(`  배치 수       : ${batchCount}개`);
    }
    if (dryRun) {
        console.log('\n[DRY-RUN] 실제 데이터는 변경되지 않았습니다.');
        console.log('실제 실행하려면 --dry-run 플래그 없이 실행하세요.');
    }
    console.log(`${'='.repeat(60)}\n`);
}

// ============================================================
// 실행
// ============================================================
const isDryRun = process.argv.includes('--dry-run');

migrateLinksToOutgoing(isDryRun)
    .then(() => process.exit(0))
    .catch(err => {
        console.error('\n❌ 마이그레이션 실패:', err);
        process.exit(1);
    });
