import webpush from 'web-push';
import { db } from '../config/database.js';
import { pushSubscriptions, users } from '../db/schema.js';
import { eq, and } from 'drizzle-orm';
import { logger } from '../utils/logger.js';

// Configure web-push with VAPID keys
if (process.env.VAPID_PUBLIC_KEY && process.env.VAPID_PRIVATE_KEY) {
  webpush.setVapidDetails(
    process.env.VAPID_SUBJECT || 'mailto:admin@example.com',
    process.env.VAPID_PUBLIC_KEY,
    process.env.VAPID_PRIVATE_KEY
  );
  logger.info('Web Push configured with VAPID keys');
} else {
  logger.warn('VAPID keys not configured - push notifications disabled');
}

/**
 * Save a push subscription for a user
 */
export const saveSubscription = async (userId, subscription) => {
  const { endpoint, keys } = subscription;

  // Check if subscription already exists
  const existing = await db
    .select()
    .from(pushSubscriptions)
    .where(
      and(
        eq(pushSubscriptions.userId, userId),
        eq(pushSubscriptions.endpoint, endpoint)
      )
    )
    .limit(1);

  if (existing.length > 0) {
    // Update existing subscription
    await db
      .update(pushSubscriptions)
      .set({
        p256dh: keys.p256dh,
        auth: keys.auth,
      })
      .where(eq(pushSubscriptions.id, existing[0].id));
  } else {
    // Create new subscription
    await db.insert(pushSubscriptions).values({
      userId,
      endpoint,
      p256dh: keys.p256dh,
      auth: keys.auth,
    });
  }

  return { success: true };
};

/**
 * Remove a push subscription
 */
export const removeSubscription = async (userId, endpoint) => {
  await db
    .delete(pushSubscriptions)
    .where(
      and(
        eq(pushSubscriptions.userId, userId),
        eq(pushSubscriptions.endpoint, endpoint)
      )
    );

  return { success: true };
};

/**
 * Remove all subscriptions for a user
 */
export const removeAllSubscriptions = async (userId) => {
  await db
    .delete(pushSubscriptions)
    .where(eq(pushSubscriptions.userId, userId));

  return { success: true };
};

/**
 * Send a push notification to a specific user
 */
export const sendPushNotification = async (userId, payload) => {
  if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
    logger.warn('Push notification skipped - VAPID keys not configured');
    return { success: false, reason: 'not_configured' };
  }

  const subscriptions = await db
    .select()
    .from(pushSubscriptions)
    .where(eq(pushSubscriptions.userId, userId));

  if (subscriptions.length === 0) {
    return { success: false, reason: 'no_subscriptions' };
  }

  const results = await Promise.allSettled(
    subscriptions.map(async (sub) => {
      const pushSubscription = {
        endpoint: sub.endpoint,
        keys: {
          p256dh: sub.p256dh,
          auth: sub.auth,
        },
      };

      try {
        await webpush.sendNotification(
          pushSubscription,
          JSON.stringify(payload)
        );
        return { success: true, endpoint: sub.endpoint };
      } catch (error) {
        // 410 Gone means subscription expired
        if (error.statusCode === 410 || error.statusCode === 404) {
          logger.info(`Removing expired subscription for user ${userId}`);
          await db
            .delete(pushSubscriptions)
            .where(eq(pushSubscriptions.id, sub.id));
        } else {
          logger.error('Push notification error', error);
        }
        return { success: false, endpoint: sub.endpoint, error: error.message };
      }
    })
  );

  const successful = results.filter(r => r.status === 'fulfilled' && r.value.success).length;
  return { success: successful > 0, sent: successful, total: subscriptions.length };
};

/**
 * Send push notification to multiple users
 */
export const sendPushNotificationToUsers = async (userIds, payload, excludeUserId = null) => {
  const targetUserIds = excludeUserId
    ? userIds.filter(id => id !== excludeUserId)
    : userIds;

  const results = await Promise.allSettled(
    targetUserIds.map(userId => sendPushNotification(userId, payload))
  );

  return results;
};

/**
 * Check if user has push notifications enabled
 */
export const hasActiveSubscription = async (userId) => {
  const subscriptions = await db
    .select({ id: pushSubscriptions.id })
    .from(pushSubscriptions)
    .where(eq(pushSubscriptions.userId, userId))
    .limit(1);

  return subscriptions.length > 0;
};

/**
 * Get VAPID public key for client
 */
export const getVapidPublicKey = () => {
  return process.env.VAPID_PUBLIC_KEY || null;
};
