import { NextResponse } from 'next/server';
import { withErrorHandler } from '@server/middleware/withErrorHandler';
import { withAuth, AuthedRequest } from '@server/middleware/withAuth';
import {
  getPlatformSettings,
  savePlatformSettings,
  createAuditLog,
} from '@server/services/admin.service';
import { ForbiddenError } from '@server/errors';

function maskKey(key: unknown): string | undefined {
  if (!key || typeof key !== 'string' || key.length === 0) return undefined;
  return key.length > 8 ? key.slice(0, 4) + '...' + key.slice(-4) : '****';
}

export const GET = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    if (req.session.role !== 'superadmin' && req.session.role !== 'support') {
      throw new ForbiddenError();
    }
    const raw = await getPlatformSettings();

    // ── One-time legacy migration ────────────────────────────────────────────
    // If new dual-bucket keys are absent but the legacy single key exists,
    // distribute into the correct bucket AND set the mode so runtime helpers
    // never fall back to legacy fields again.
    const legacyStripeSecret = raw.stripe_secret_key as string | undefined;
    const legacyStripePub    = raw.stripe_publishable_key as string | undefined;
    const legacyRazorpayId     = raw.razorpay_key_id as string | undefined;
    const legacyRazorpaySecret = raw.razorpay_key_secret as string | undefined;

    let stripeLiveSecret = raw.stripe_live_secret_key as string | undefined;
    let stripeLivePub    = raw.stripe_live_publishable_key as string | undefined;
    let stripeTestSecret = raw.stripe_test_secret_key as string | undefined;
    let stripeTestPub    = raw.stripe_test_publishable_key as string | undefined;

    let razorpayLiveId     = raw.razorpay_live_key_id as string | undefined;
    let razorpayLiveSecret = raw.razorpay_live_key_secret as string | undefined;
    let razorpayTestId     = raw.razorpay_test_key_id as string | undefined;
    let razorpayTestSecret = raw.razorpay_test_key_secret as string | undefined;

    const migrationPayload: Record<string, string> = {};

    let stripeMigrationMode: 'test' | 'live' | null = null;
    if (!stripeLiveSecret && !stripeTestSecret && legacyStripeSecret) {
      if (legacyStripeSecret.startsWith('sk_test_')) {
        stripeTestSecret = legacyStripeSecret;
        migrationPayload.stripe_test_secret_key = stripeTestSecret;
        stripeMigrationMode = 'test';
      } else {
        stripeLiveSecret = legacyStripeSecret;
        migrationPayload.stripe_live_secret_key = stripeLiveSecret;
        stripeMigrationMode = 'live';
      }
    }
    if (!stripeLivePub && !stripeTestPub && legacyStripePub) {
      if (legacyStripePub.startsWith('pk_test_')) {
        stripeTestPub = legacyStripePub;
        migrationPayload.stripe_test_publishable_key = stripeTestPub;
        if (!stripeMigrationMode) stripeMigrationMode = 'test';
      } else {
        stripeLivePub = legacyStripePub;
        migrationPayload.stripe_live_publishable_key = stripeLivePub;
        if (!stripeMigrationMode) stripeMigrationMode = 'live';
      }
    }
    // Persist mode if stripe_mode not yet set and we learned it from migration
    if (stripeMigrationMode && !raw.stripe_mode) {
      migrationPayload.stripe_mode = stripeMigrationMode;
    }

    let razorpayMigrationMode: 'test' | 'live' | null = null;
    if (!razorpayLiveId && !razorpayTestId && legacyRazorpayId) {
      if (legacyRazorpayId.startsWith('rzp_test_')) {
        razorpayTestId = legacyRazorpayId;
        migrationPayload.razorpay_test_key_id = razorpayTestId;
        razorpayMigrationMode = 'test';
      } else {
        razorpayLiveId = legacyRazorpayId;
        migrationPayload.razorpay_live_key_id = razorpayLiveId;
        razorpayMigrationMode = 'live';
      }
    }
    if (!razorpayLiveSecret && !razorpayTestSecret && legacyRazorpaySecret) {
      if (razorpayMigrationMode === 'test' || migrationPayload.razorpay_test_key_id) {
        razorpayTestSecret = legacyRazorpaySecret;
        migrationPayload.razorpay_test_key_secret = razorpayTestSecret;
        if (!razorpayMigrationMode) razorpayMigrationMode = 'test';
      } else {
        razorpayLiveSecret = legacyRazorpaySecret;
        migrationPayload.razorpay_live_key_secret = razorpayLiveSecret;
        if (!razorpayMigrationMode) razorpayMigrationMode = 'live';
      }
    }
    if (razorpayMigrationMode && !raw.razorpay_mode) {
      migrationPayload.razorpay_mode = razorpayMigrationMode;
    }

    // Persist migration so runtime helpers never depend on legacy fields.
    // Only write for superadmin — support is read-only and should not trigger
    // side-effecting writes on a GET request.
    if (Object.keys(migrationPayload).length > 0 && req.session.role === 'superadmin') {
      try {
        await savePlatformSettings(migrationPayload, req.session.userId);
      } catch {
        // Non-fatal — hints are still correct in this response
      }
    }

    // Effective modes: from DB, or from migration, or infer from which bucket has keys
    const effectiveStripeMode: 'test' | 'live' =
      (raw.stripe_mode as 'test' | 'live' | undefined) ??
      (stripeMigrationMode as 'test' | 'live' | null) ??
      (stripeTestSecret && !stripeLiveSecret ? 'test' : 'live');

    const effectiveRazorpayMode: 'test' | 'live' =
      (raw.razorpay_mode as 'test' | 'live' | undefined) ??
      (razorpayMigrationMode as 'test' | 'live' | null) ??
      (razorpayTestId && !razorpayLiveId ? 'test' : 'live');

    return NextResponse.json({
      settings: {
        stripe_active: (raw.stripe_active as boolean | undefined) ?? true,
        stripe_mode: effectiveStripeMode,
        stripe_currency: (raw.stripe_currency as string | undefined) ?? 'USD',
        stripe_promo_codes_enabled: (raw.stripe_promo_codes_enabled as boolean | undefined) ?? false,
        payment_grace_period_days: (raw.payment_grace_period_days as number | undefined) ?? 3,
        stripe_live_secret_key_hint: maskKey(stripeLiveSecret),
        stripe_live_publishable_key_hint: stripeLivePub ? stripeLivePub.slice(0, 7) + '...' : undefined,
        stripe_test_secret_key_hint: maskKey(stripeTestSecret),
        stripe_test_publishable_key_hint: stripeTestPub ? stripeTestPub.slice(0, 7) + '...' : undefined,
        razorpay_active: (raw.razorpay_active as boolean | undefined) ?? false,
        razorpay_mode: effectiveRazorpayMode,
        razorpay_currency: (raw.razorpay_currency as string | undefined) ?? 'INR',
        razorpay_live_key_id_hint: maskKey(razorpayLiveId),
        razorpay_live_key_secret_hint: maskKey(razorpayLiveSecret),
        razorpay_test_key_id_hint: maskKey(razorpayTestId),
        razorpay_test_key_secret_hint: maskKey(razorpayTestSecret),
      },
    });
  })
);

export const PUT = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    if (req.session.role !== 'superadmin') {
      throw new ForbiddenError();
    }
    const body = await req.json();
    const payload: Record<string, unknown> = {};

    if ('stripe_active' in body) payload.stripe_active = Boolean(body.stripe_active);
    if ('stripe_mode' in body && (body.stripe_mode === 'test' || body.stripe_mode === 'live')) payload.stripe_mode = body.stripe_mode;
    if ('stripe_currency' in body) payload.stripe_currency = String(body.stripe_currency).toUpperCase();
    if ('stripe_promo_codes_enabled' in body) payload.stripe_promo_codes_enabled = Boolean(body.stripe_promo_codes_enabled);
    if ('payment_grace_period_days' in body) payload.payment_grace_period_days = parseInt(body.payment_grace_period_days, 10) || 3;

    if (body.stripe_live_secret_key?.trim()) payload.stripe_live_secret_key = body.stripe_live_secret_key.trim();
    if (body.stripe_live_publishable_key?.trim()) payload.stripe_live_publishable_key = body.stripe_live_publishable_key.trim();
    if (body.stripe_test_secret_key?.trim()) payload.stripe_test_secret_key = body.stripe_test_secret_key.trim();
    if (body.stripe_test_publishable_key?.trim()) payload.stripe_test_publishable_key = body.stripe_test_publishable_key.trim();

    if ('razorpay_active' in body) payload.razorpay_active = Boolean(body.razorpay_active);
    if ('razorpay_mode' in body && (body.razorpay_mode === 'test' || body.razorpay_mode === 'live')) payload.razorpay_mode = body.razorpay_mode;
    if ('razorpay_currency' in body) payload.razorpay_currency = String(body.razorpay_currency).toUpperCase();

    if (body.razorpay_live_key_id?.trim()) payload.razorpay_live_key_id = body.razorpay_live_key_id.trim();
    if (body.razorpay_live_key_secret?.trim()) payload.razorpay_live_key_secret = body.razorpay_live_key_secret.trim();
    if (body.razorpay_test_key_id?.trim()) payload.razorpay_test_key_id = body.razorpay_test_key_id.trim();
    if (body.razorpay_test_key_secret?.trim()) payload.razorpay_test_key_secret = body.razorpay_test_key_secret.trim();

    await savePlatformSettings(payload, req.session.userId);
    await createAuditLog({
      actorId: req.session.userId,
      actorEmail: req.session.email,
      actorType: 'admin',
      action: 'Updated gateway settings',
      resource: 'platform_settings',
      severity: 'info',
      metadata: { changedKeys: Object.keys(payload) },
    });

    return NextResponse.json({ ok: true });
  })
);
