import * as admin from 'firebase-admin';

// Firebase Admin SDK 초기화 (GOOGLE_APPLICATION_CREDENTIALS 환경변수 사용)
// Usage (dry-run): ts-node -P scripts/tsconfig.json scripts/backfill-custom-claims.ts
// Usage (execute): ts-node -P scripts/tsconfig.json scripts/backfill-custom-claims.ts --execute

if (!admin.apps.length) {
  admin.initializeApp();
}

const db = admin.firestore();
const auth = admin.auth();

// ── 상수 ─────────────────────────────────────────────────────────────────────

const VALID_ROLES = ['admin', 'reviewer', 'member', 'guest'] as const;
type Role = (typeof VALID_ROLES)[number];

const BATCH_SIZE = 10; // Firebase Auth API rate limit 방지

// ── 타입 정의 ─────────────────────────────────────────────────────────────────

interface BackfillResult {
  total: number;
  processed: number;
  skipped: number;
  errors: number;
}

interface UserResult {
  uid: string;
  role: Role;
  status: 'success' | 'skipped_no_user' | `error: ${string}`;
}

// ── 핵심 함수 ─────────────────────────────────────────────────────────────────

function resolveRole(rawRole: unknown): Role {
  if (typeof rawRole === 'string' && (VALID_ROLES as readonly string[]).includes(rawRole)) {
    return rawRole as Role;
  }
  return 'guest';
}

async function processBatch(
  docs: FirebaseFirestore.QueryDocumentSnapshot[],
  dryRun: boolean,
): Promise<{ processed: number; skipped: number; errors: number; details: UserResult[] }> {
  let processed = 0;
  let skipped = 0;
  let errors = 0;
  const details: UserResult[] = [];

  await Promise.all(
    docs.map(async (userDoc) => {
      const uid = userDoc.id;
      const rawRole = userDoc.data()?.role;
      const role = resolveRole(rawRole);

      if (dryRun) {
        console.log(`  [DRY-RUN] uid=${uid} → role=${role}${rawRole !== role ? ` (원본: "${rawRole}" → 기본값 guest)` : ''}`);
        processed++;
        details.push({ uid, role, status: 'success' });
        return;
      }

      try {
        // Firebase Auth에 해당 uid의 유저가 존재하는지 확인
        await auth.getUser(uid);
        await auth.setCustomUserClaims(uid, { role });
        processed++;
        details.push({ uid, role, status: 'success' });
      } catch (error: any) {
        // uid에 해당하는 Auth 유저가 없는 경우 (Firestore only 문서)
        if (error.code === 'auth/user-not-found') {
          skipped++;
          details.push({ uid, role, status: 'skipped_no_user' });
          console.warn(`  [SKIP] uid=${uid} → Auth 유저 없음 (Firestore only)`);
        } else {
          errors++;
          const msg = error.message ?? String(error);
          details.push({ uid, role, status: `error: ${msg}` });
          console.error(`  [ERROR] uid=${uid} → ${msg}`);
        }
      }
    }),
  );

  return { processed, skipped, errors, details };
}

async function backfillCustomClaims(dryRun: boolean): Promise<BackfillResult> {
  console.log(`[INFO] Custom Claims 백필 시작 (dryRun=${dryRun})`);

  const result: BackfillResult = {
    total: 0,
    processed: 0,
    skipped: 0,
    errors: 0,
  };

  const snapshot = await db.collection('users').get();
  result.total = snapshot.docs.length;

  console.log(`[INFO] 전체 유저 수: ${result.total}\n`);

  const totalBatches = Math.ceil(snapshot.docs.length / BATCH_SIZE);

  for (let i = 0; i < snapshot.docs.length; i += BATCH_SIZE) {
    const batchDocs = snapshot.docs.slice(i, i + BATCH_SIZE);
    const batchNum = Math.floor(i / BATCH_SIZE) + 1;

    console.log(`[INFO] 배치 ${batchNum}/${totalBatches} 처리 중 (${batchDocs.length}건)...`);

    const batchResult = await processBatch(batchDocs, dryRun);

    result.processed += batchResult.processed;
    result.skipped += batchResult.skipped;
    result.errors += batchResult.errors;
  }

  return result;
}

// ── 엔트리포인트 ─────────────────────────────────────────────────────────────

async function main() {
  const dryRun = !process.argv.includes('--execute');

  if (dryRun) {
    console.log('[DRY-RUN] --execute 플래그 없이 실행 중입니다. Custom Claims 실제 쓰기는 발생하지 않습니다.');
    console.log('[DRY-RUN] 실제 실행: ts-node -P scripts/tsconfig.json scripts/backfill-custom-claims.ts --execute\n');
  } else {
    console.log('[EXECUTE] Firebase Auth Custom Claims 실제 쓰기가 실행됩니다.\n');
  }

  const result = await backfillCustomClaims(dryRun);

  console.log('\n========== Custom Claims 백필 완료 ==========');
  console.log(`전체 유저 수  : ${result.total}`);
  console.log(`처리 완료     : ${result.processed}${dryRun ? ' (dry-run, 실제 쓰기 없음)' : ''}`);
  console.log(`스킵 수       : ${result.skipped} (Auth 유저 없음)`);
  console.log(`오류 수       : ${result.errors}`);
  console.log('=============================================');

  if (result.errors > 0) {
    process.exit(1);
  }
}

main().catch((err) => {
  console.error('[FATAL]', err);
  process.exit(1);
});
