/**
 * Push notification smoke test.
 * Verifies Firebase init, lists stored device tokens, and sends a real test
 * notification to every token in the DB (or a specific one via --token flag).
 *
 * Usage:
 *   npm run test:push                      — send to all tokens in DB
 *   npm run test:push -- --token <fcmToken> — send to one specific token
 *
 * Run from apps/api/
 */

/* eslint-disable no-console */

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

const c = {
  green:  (s: string) => `\x1b[32m${s}\x1b[0m`,
  red:    (s: string) => `\x1b[31m${s}\x1b[0m`,
  yellow: (s: string) => `\x1b[33m${s}\x1b[0m`,
  cyan:   (s: string) => `\x1b[36m${s}\x1b[0m`,
  bold:   (s: string) => `\x1b[1m${s}\x1b[0m`,
};

function log(icon: string, msg: string) { console.log(`${icon}  ${msg}`); }

async function initFirebase(): Promise<any> {
  const raw  = process.env.FIREBASE_SERVICE_ACCOUNT_JSON;
  const path = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;

  if (!raw && !path) {
    console.error(c.red('✗ Neither FIREBASE_SERVICE_ACCOUNT_JSON nor FIREBASE_SERVICE_ACCOUNT_PATH is set in .env'));
    process.exit(1);
  }

  log('🔑', `Using ${raw ? 'FIREBASE_SERVICE_ACCOUNT_JSON (inline JSON)' : `FIREBASE_SERVICE_ACCOUNT_PATH (${path})`}`);

  let serviceAccount: any;
  try {
    serviceAccount = raw ? JSON.parse(raw) : await import(path!);
  } catch (e: any) {
    console.error(c.red(`✗ Failed to parse service account: ${e.message}`));
    process.exit(1);
  }

  log('✔', c.green(`Service account parsed — project_id: ${serviceAccount.project_id}, client_email: ${serviceAccount.client_email}`));

  const admin = await import('firebase-admin');
  if (!admin.apps.length) {
    admin.initializeApp({ credential: admin.credential.cert(serviceAccount) });
  }

  log('✔', c.green('Firebase Admin SDK initialised'));
  return admin.messaging();
}

async function run() {
  console.log(c.bold('\n── Gate Pass Push Notification Test ──\n'));

  // Step 1 — Firebase
  const messaging = await initFirebase();

  // Step 2 — Determine tokens to test
  const tokenArgIdx = process.argv.indexOf('--token');
  const specificToken = tokenArgIdx !== -1 ? process.argv[tokenArgIdx + 1] : null;

  let tokens: { id: string; token: string; platform: string }[] = [];

  if (specificToken) {
    tokens = [{ id: 'cli', token: specificToken, platform: 'unknown' }];
    log('🎯', `Target token supplied via --token flag`);
  } else {
    tokens = await prisma.deviceToken.findMany({
      select: { id: true, token: true, platform: true },
    });

    if (tokens.length === 0) {
      console.error(c.red('\n✗ No device tokens found in DB. Log in on a mobile device first so the app registers a token.'));
      process.exit(1);
    }

    log('📱', `Found ${tokens.length} device token(s) in DB:`);
    tokens.forEach((t) =>
      console.log(`     id=${t.id}  platform=${t.platform}  token=${t.token.slice(0, 20)}…`)
    );
  }

  // Step 3 — Send test notification
  console.log('');
  log('📤', 'Sending test notification…\n');

  const result = await messaging.sendEachForMulticast({
    tokens: tokens.map((t) => t.token),
    notification: {
      title: '🔔 Gate Pass Test',
      body:  'Push notification is working correctly!',
    },
    data: { kind: 'test' },
    apns: { payload: { aps: { sound: 'default' } } },
  });

  // Step 4 — Report
  result.responses.forEach((r: any, i: number) => {
    const t = tokens[i];
    if (r.success) {
      log('✔', c.green(`Token ${i + 1} (${t.platform}) — SUCCESS  messageId: ${r.messageId}`));
    } else {
      const code = r.error?.code || 'unknown';
      const msg  = r.error?.message || '';
      log('✗', c.red(`Token ${i + 1} (${t.platform}) — FAILED   code: ${code}`));
      if (msg) console.log(`     ${c.yellow(msg)}`);

      if (code === 'messaging/registration-token-not-registered' || code === 'messaging/invalid-registration-token') {
        console.log(`     ${c.yellow('→ Token is stale/invalid. The device needs to re-register (log out and back in on the mobile app).')}`);
      } else if (code === 'messaging/invalid-argument') {
        console.log(`     ${c.yellow('→ Token format is wrong. Make sure the app is sending an FCM token, not a raw APNs token.')}`);
      } else if (code === 'messaging/authentication-error' || code === 'messaging/server-error') {
        console.log(`     ${c.yellow('→ Firebase credentials may be invalid or the service account lacks the correct role. Check Firebase Console → Service Accounts.')}`);
      }
    }
  });

  console.log('');
  log('📊', `Results: ${c.green(`${result.successCount} succeeded`)}  ${result.failureCount > 0 ? c.red(`${result.failureCount} failed`) : `${result.failureCount} failed`}`);

  await prisma.$disconnect();
}

run().catch((e) => {
  console.error(c.red(`\nFatal error: ${e.message}`));
  prisma.$disconnect();
  process.exit(1);
});
