/**
 * Admin routes for referrals partition key migration.
 *
 * POST /referrals/migration/backfill    — trigger backfill from old → new container
 * GET  /referrals/migration/status      — get migration status (counts, mode)
 * GET  /referrals/migration/verify      — verify consistency between containers
 * POST /referrals/migration/mode        — switch migration mode (dual-write | new-only | old-only)
 *
 * All routes require admin role.
 * Registered at prefix: /api/admin
 */

import type { FastifyInstance } from 'fastify';
import { getRequestProductId } from '../../lib/request-context.js';
import { requireRole } from '../../lib/auth.js';
import {
  getMigrationStatus,
  backfillOldToNew,
  verifyConsistency,
  type MigrationMode,
} from '../referrals/migration-repository.js';
import { BadRequestError } from '../../lib/errors.js';

const VALID_MODES: MigrationMode[] = ['dual-write', 'new-only', 'old-only'];

export async function referralMigrationAdminRoutes(app: FastifyInstance) {
  // All routes require admin
  app.addHook('preHandler', async (req) => {
    await requireRole(req, 'admin');
  });

  /**
   * GET /referrals/migration/status
   *
   * Returns current migration status:
   * - mode: current migration mode
   * - oldContainerCount: documents in old container
   * - newContainerCount: documents in new container
   * - pendingBackfillCount: documents needing backfill
   */
  app.get('/referrals/migration/status', async (req) => {
    const productId = getRequestProductId(req);
    const status = await getMigrationStatus(productId);
    return status;
  });

  /**
   * POST /referrals/migration/backfill
   *
   * Trigger backfill from old container to new container.
   * Idempotent — safe to run multiple times.
   *
   * Query params:
   * - batchSize: number of docs per batch (default: 100, max: 500)
   *
   * Returns:
   * - migrated: number of docs migrated in this run
   * - skipped: number already existing
   * - errors: array of error messages
   */
  app.post('/referrals/migration/backfill', async (req) => {
    const productId = getRequestProductId(req);
    const { batchSize = '100' } = req.query as { batchSize?: string };

    const size = Math.min(parseInt(batchSize, 10) || 100, 500);
    const result = await backfillOldToNew(productId, size);

    return {
      success: true,
      migrated: result.migrated,
      skipped: result.skipped,
      errors: result.errors,
      message:
        result.errors.length > 0
          ? `Backfill completed with ${result.errors.length} errors`
          : `Backfill completed: ${result.migrated} migrated, ${result.skipped} skipped`,
    };
  });

  /**
   * GET /referrals/migration/verify
   *
   * Verify consistency between old and new containers.
   * Returns list of inconsistencies (should be empty after successful backfill).
   *
   * Query params:
   * - includePending: include "pending backfill" items in results (default: false)
   *
   * Returns:
   * - consistent: true if no inconsistencies found
   * - inconsistencies: array of {id, issue} objects
   * - count: total number of inconsistencies
   */
  app.get('/referrals/migration/verify', async (req) => {
    const productId = getRequestProductId(req);
    const { includePending = 'false' } = req.query as { includePending?: string };

    const allInconsistencies = await verifyConsistency(productId);
    const showPending = includePending === 'true';

    const filtered = showPending
      ? allInconsistencies
      : allInconsistencies.filter((i) => !i.issue.includes('pending backfill'));

    return {
      consistent: filtered.length === 0,
      count: filtered.length,
      totalPending: allInconsistencies.filter((i) => i.issue.includes('pending backfill')).length,
      inconsistencies: filtered.slice(0, 100), // Limit response size
    };
  });

  /**
   * POST /referrals/migration/mode
   *
   * Switch migration mode. Requires confirmation for destructive modes.
   *
   * Body:
   * - mode: 'dual-write' | 'new-only' | 'old-only'
   * - confirm: boolean (required for 'old-only' mode)
   *
   * Returns:
   * - success: true
   * - previousMode: previous mode
   * - currentMode: new mode
   * - warning: optional warning message
   */
  app.post('/referrals/migration/mode', async (req) => {
    const { mode, confirm } = req.body as { mode: string; confirm?: boolean };

    if (!VALID_MODES.includes(mode as MigrationMode)) {
      throw new BadRequestError(
        `Invalid mode: ${mode}. Must be one of: ${VALID_MODES.join(', ')}`
      );
    }

    const previousMode = (process.env.REFERRAL_MIGRATION_MODE || 'dual-write') as MigrationMode;

    // Require confirmation for reverting to old-only
    if (mode === 'old-only' && previousMode !== 'old-only' && !confirm) {
      throw new BadRequestError(
        'Switching to old-only mode requires confirm=true. This is a destructive operation that may lose data written to the new container.'
      );
    }

    // Update environment variable (effective for this process only)
    // For persistent change, update deployment config
    process.env.REFERRAL_MIGRATION_MODE = mode;

    const warning =
      mode === 'new-only'
        ? 'New-only mode: All reads and writes now use referrals_v2 container only. Ensure backfill is complete before using in production.'
        : mode === 'old-only'
          ? 'Old-only mode: Reverted to original container. Data written to referrals_v2 during dual-write mode may not be visible.'
          : undefined;

    return {
      success: true,
      previousMode,
      currentMode: mode,
      warning,
      note: 'Mode change is in-memory only. Update REFERRAL_MIGRATION_MODE env var in deployment config for persistence.',
    };
  });
}
