/**
 * Email Preferences Helper
 * 
 * Handles admin-level and user-level email notification preferences
 * Logic: Email only sent if BOTH admin AND user have it enabled
 */

import { User } from '@models/User';
import { SYSTEM_CONFIG } from '../config/system.config';
import { getConfigValue } from '../services/configReader.service';
import logger from '../utils/logger';

/**
 * Email notification types that can be controlled
 */
export enum EmailNotificationType {
  REQUEST_CREATED = 'request_created',
  APPROVAL_REQUEST = 'approval_request',
  REQUEST_APPROVED = 'request_approved',
  REQUEST_REJECTED = 'request_rejected',
  TAT_REMINDER = 'tat_reminder',  // Generic TAT reminder (any threshold)
  TAT_BREACHED = 'tat_breached',  // 100% breach
  WORKFLOW_RESUMED = 'workflow_resumed',
  REQUEST_CLOSED = 'request_closed',
  WORKFLOW_PAUSED = 'workflow_paused',
  PARTICIPANT_ADDED = 'participant_added',
  SPECTATOR_ADDED = 'spectator_added',
  APPROVER_SKIPPED = 'approver_skipped',
  // Dealer Claim Specific
  DEALER_PROPOSAL_SUBMITTED = 'dealer_proposal_submitted',
  ACTIVITY_CREATED = 'activity_created',
  COMPLETION_DOCUMENTS_SUBMITTED = 'completion_documents_submitted',
  EINVOICE_GENERATED = 'einvoice_generated',
  CREDIT_NOTE_SENT = 'credit_note_sent',
  ADDITIONAL_DOCUMENT_ADDED = 'additional_document_added',
  RE_QUOTATION = 're_quotation',
}

/**
 * Check if email should be sent based on admin and user preferences
 * 
 * @param userId - User ID to check preferences for
 * @param emailType - Type of email notification
 * @returns true if email should be sent, false otherwise
 */
export async function shouldSendEmail(
  userId: string,
  emailType: EmailNotificationType
): Promise<boolean> {
  try {
    // Step 1: Check admin-level configuration (System Config)
    const adminEmailEnabled = await isAdminEmailEnabled(emailType);

    if (!adminEmailEnabled) {
      logger.info(`[Email] Admin disabled emails for ${emailType} - skipping`);
      return false;
    }

    // Step 2: Check user-level preferences
    const userEmailEnabled = await isUserEmailEnabled(userId, emailType);

    if (!userEmailEnabled) {
      logger.info(`[Email] User ${userId} disabled emails for ${emailType} - skipping`);
      return false;
    }

    // Both admin AND user have enabled - send email
    logger.info(`[Email] Email enabled for user ${userId}, type: ${emailType}`);
    return true;

  } catch (error) {
    logger.error(`[Email] Error checking email preferences for ${userId}:`, error);
    // On error, default to NOT sending email (safe default)
    return false;
  }
}

/**
 * Check if admin has enabled emails globally
 * Checks database configuration first, then falls back to environment variable
 */
async function isAdminEmailEnabled(emailType: EmailNotificationType): Promise<boolean> {
  try {
    // Step 1: Check database configuration (admin panel setting)
    const dbConfigValue = await getConfigValue('ENABLE_EMAIL_NOTIFICATIONS', '');

    if (dbConfigValue) {
      // Parse database value (it's stored as string 'true' or 'false')
      const dbEnabled = dbConfigValue.toLowerCase() === 'true';

      if (!dbEnabled) {
        logger.info('[Email] Admin has disabled email notifications globally (from database config)');
        return false;
      }

      logger.debug('[Email] Email notifications enabled (from database config)');
      return true;
    }

    // Step 2: Fall back to environment variable if database config not found
    const envEnabled = SYSTEM_CONFIG.NOTIFICATIONS.ENABLE_EMAIL;

    if (!envEnabled) {
      logger.info('[Email] Admin has disabled email notifications globally (from environment variable)');
      return false;
    }

    logger.debug('[Email] Email notifications enabled (from environment variable)');
    return true;
  } catch (error) {
    logger.error('[Email] Error checking admin email configuration, defaulting to enabled:', error);
    // On error, default to enabled (safe default to avoid blocking notifications)
    return true;
  }
}

/**
 * Check if user has enabled emails
 * Uses existing User.emailNotificationsEnabled field
 */
async function isUserEmailEnabled(userId: string, emailType: EmailNotificationType): Promise<boolean> {
  try {
    // Fetch user and check emailNotificationsEnabled field
    const user = await User.findByPk(userId, {
      attributes: ['userId', 'emailNotificationsEnabled']
    });

    if (!user) {
      logger.warn(`[Email] User ${userId} not found - defaulting to enabled`);
      return true;
    }

    // Check user's global email notification setting
    const enabled = (user as any).emailNotificationsEnabled !== false;

    if (!enabled) {
      logger.info(`[Email] User ${userId} has disabled email notifications globally`);
    }

    return enabled;
  } catch (error) {
    logger.warn('[Email] Error checking user email preference (defaulting to enabled):', error);
    return true;
  }
}

/**
 * Check if in-app notification should be sent
 * Uses existing User.inAppNotificationsEnabled field
 */
export async function shouldSendInAppNotification(
  userId: string,
  notificationType: string
): Promise<boolean> {
  try {
    // Check admin config first (if SystemConfig model exists)
    const adminEnabled = await isAdminInAppEnabled(notificationType);

    if (!adminEnabled) {
      return false;
    }

    // Fetch user and check inAppNotificationsEnabled field
    const user = await User.findByPk(userId, {
      attributes: ['userId', 'inAppNotificationsEnabled']
    });

    if (!user) {
      logger.warn(`[Notification] User ${userId} not found - defaulting to enabled`);
      return true;
    }

    // Check user's global in-app notification setting
    const enabled = (user as any).inAppNotificationsEnabled !== false;

    if (!enabled) {
      logger.info(`[Notification] User ${userId} has disabled in-app notifications globally`);
    }

    return enabled;
  } catch (error) {
    logger.warn('[Notification] Error checking in-app notification preference (defaulting to enabled):', error);
    return true;
  }
}

/**
 * Check if admin has enabled in-app notifications globally
 * Checks database configuration first, then falls back to environment variable
 */
async function isAdminInAppEnabled(notificationType: string): Promise<boolean> {
  try {
    // Step 1: Check database configuration (admin panel setting)
    const dbConfigValue = await getConfigValue('ENABLE_IN_APP_NOTIFICATIONS', '');

    if (dbConfigValue) {
      // Parse database value (it's stored as string 'true' or 'false')
      const dbEnabled = dbConfigValue.toLowerCase() === 'true';

      if (!dbEnabled) {
        logger.info('[Notification] Admin has disabled in-app notifications globally (from database config)');
        return false;
      }

      logger.debug('[Notification] In-app notifications enabled (from database config)');
      return true;
    }

    // Step 2: Fall back to environment variable if database config not found
    const envValue = process.env.ENABLE_IN_APP_NOTIFICATIONS;
    if (envValue !== undefined) {
      const envEnabled = envValue.toLowerCase() === 'true';
      if (!envEnabled) {
        logger.info('[Notification] Admin has disabled in-app notifications globally (from environment variable)');
        return false;
      }
      logger.debug('[Notification] In-app notifications enabled (from environment variable)');
      return true;
    }

    // Step 3: Final fallback to system config (defaults to true)
    const adminInAppEnabled = SYSTEM_CONFIG.NOTIFICATIONS.ENABLE_IN_APP;

    if (!adminInAppEnabled) {
      logger.info('[Notification] Admin has disabled in-app notifications globally (from system config)');
      return false;
    }

    logger.debug('[Notification] In-app notifications enabled (from system config default)');
    return true;
  } catch (error) {
    logger.error('[Notification] Error checking admin in-app notification configuration, defaulting to enabled:', error);
    // On error, default to enabled (safe default to avoid blocking notifications)
    return true;
  }
}

/**
 * Batch check for multiple users
 * Returns array of user IDs who should receive the email
 */
export async function filterUsersForEmail(
  userIds: string[],
  emailType: EmailNotificationType
): Promise<string[]> {
  const enabledUsers: string[] = [];

  for (const userId of userIds) {
    const shouldSend = await shouldSendEmail(userId, emailType);
    if (shouldSend) {
      enabledUsers.push(userId);
    }
  }

  return enabledUsers;
}

/**
 * Critical emails that should ALWAYS be sent (override preferences)
 * These are too important to be disabled
 */
export const CRITICAL_EMAILS = [
  EmailNotificationType.REQUEST_REJECTED,
  EmailNotificationType.TAT_BREACHED
];

/**
 * Check if email should be sent, with critical email override
 */
export async function shouldSendEmailWithOverride(
  userId: string,
  emailType: EmailNotificationType
): Promise<boolean> {
  // emails always sent (override user preference)
  if (CRITICAL_EMAILS.includes(emailType)) {
    const adminEnabled = await isAdminEmailEnabled(emailType);
    if (adminEnabled) {
      logger.info(`[Email] Critical email ${emailType} - sending despite user preference`);
      return true;
    }
  }

  // Non-critical emails - check both admin and user preferences
  return await shouldSendEmail(userId, emailType);
}

