/**
 * Feature Request Notification Service
 *
 * Fire-and-forget helper that sends email notifications for feature request
 * activities (new request, status change, comment, etc.) to the addresses
 * configured in the Super Admin Settings.
 *
 * It never throws — a failed notification must never break the calling route.
 * Every call also creates a FeatureRequestNotificationLog document for audit.
 */

import { getModels } from '../models';
import { sendNotificationEmail } from './email/systemEmails';
import { notificationService } from './notificationService';
import type { FeatureRequestActivityType } from '../models/FeatureRequestNotificationLog';

// ── Default config (applied when the field is missing from panelSettings) ────

export const DEFAULT_FEATURE_REQUEST_NOTIFICATIONS = {
  enabled: false,
  recipients: [] as string[],
  activities: {
    created: true,
    status_update: true,
    approved: true,
    rejected: true,
    done: true,
    comment_added: true,
    edited: true,
    withdrawn: true,
    deleted: true,
  },
};

// ── Activity metadata for email subjects ─────────────────────────────────────

const ACTIVITY_LABELS: Record<string, string> = {
  created: 'New Feature Request',
  status_update: 'Feature Request Status Updated',
  approved: 'Feature Request Approved',
  rejected: 'Feature Request Rejected',
  done: 'Feature Request Completed',
  comment_added: 'New Comment on Feature Request',
  edited: 'Feature Request Updated',
  withdrawn: 'Feature Request Withdrawn',
  deleted: 'Feature Request Deleted',
};

// ── Types ────────────────────────────────────────────────────────────────────

interface NotifyParams {
  activityType: FeatureRequestActivityType;
  featureRequestId: string;
  featureRequestTitle: string;
  triggeredByUserId: string;
  triggeredByUserName: string;
  triggeredByUserRole: string;
  details?: {
    status?: string;
    adminNote?: string;
    commentContent?: string;
    previousStatus?: string;
  };
}

// ── Helper: load the notification config from the super-admin user ───────────

async function getNotificationConfig(): Promise<typeof DEFAULT_FEATURE_REQUEST_NOTIFICATIONS> {
  try {
    const { User } = getModels();
    const superAdmin = await User.findOne({ role: 'super-admin' }).lean();
    const raw = (superAdmin as any)?.panelSettings?.featureRequestNotifications;
    if (!raw) return { ...DEFAULT_FEATURE_REQUEST_NOTIFICATIONS };
    return {
      enabled: raw.enabled ?? false,
      recipients: raw.recipients ?? [],
      activities: {
        ...DEFAULT_FEATURE_REQUEST_NOTIFICATIONS.activities,
        ...(raw.activities || {}),
      },
    };
  } catch (err: any) {
    console.warn('[FeatureRequestNotifications] Failed to load config:', err?.message);
    return { ...DEFAULT_FEATURE_REQUEST_NOTIFICATIONS };
  }
}

// ── In-app notifications ─────────────────────────────────────────────────────

/** Activity types that concern the person who raised the request. */
const REQUESTER_ACTIVITIES: Record<string, { type: string; title: string }> = {
  approved: { type: 'feature_request.approved', title: 'Your feature request was approved' },
  rejected: { type: 'feature_request.rejected', title: 'Your feature request was rejected' },
  done: { type: 'feature_request.status_changed', title: 'Your feature request is done' },
  status_update: { type: 'feature_request.status_changed', title: 'Your feature request was updated' },
  comment_added: { type: 'feature_request.comment_added', title: 'New comment on your feature request' },
};

/**
 * Raise in-app notifications for a feature request activity.
 *
 * Two audiences, deliberately kept apart:
 *   - a NEW request goes to the reviewers (Super Admin, and the org's admins),
 *   - a DECISION goes back to whoever raised it.
 *
 * Never throws — the caller is already fire-and-forget.
 */
async function raiseInAppNotifications(params: NotifyParams): Promise<void> {
  try {
    const { FeatureRequest } = getModels();
    const request = await FeatureRequest.findById(params.featureRequestId);
    if (!request) return;

    const actionUrl = `/request-feature?id=${params.featureRequestId}`;
    const common = {
      module: 'request-feature',
      entityType: 'feature-request',
      entityId: params.featureRequestId,
      actorUserId: params.triggeredByUserId,
      actorName: params.triggeredByUserName,
      actionUrl,
    };

    if (params.activityType === 'created') {
      // Reviewers: the platform owner and the requesting organisation's admins.
      await notificationService.notifyRole('super-admin', {
        ...common,
        type: 'feature_request.created',
        message: `${params.triggeredByUserName} requested: ${params.featureRequestTitle}`,
      });

      if (request.companyId) {
        await notificationService.notifyOrgRole(String(request.companyId), 'admin', {
          ...common,
          type: 'feature_request.created',
          message: `${params.triggeredByUserName} requested: ${params.featureRequestTitle}`,
        });
      }
      return;
    }

    // Decisions and updates go back to the requester — but never as an echo of
    // their own action (editing or withdrawing your own request notifies nobody).
    const mapped = REQUESTER_ACTIVITIES[params.activityType];
    if (!mapped || !request.userId) return;
    if (String(request.userId) === String(params.triggeredByUserId)) return;

    await notificationService.notifyUser(String(request.userId), {
      ...common,
      type: mapped.type,
      title: mapped.title,
      message: params.details?.adminNote
        ? `${params.featureRequestTitle} — ${params.details.adminNote}`
        : params.featureRequestTitle,
      organizationId: request.companyId ? String(request.companyId) : null,
    });
  } catch (err: any) {
    console.warn('[FeatureRequestNotifications] In-app notification failed:', err?.message);
  }
}

// ── Main function ─────────────────────────────────────────────────────────────

export async function notifyFeatureRequestActivity(params: NotifyParams): Promise<void> {
  const {
    activityType,
    featureRequestId,
    featureRequestTitle,
    triggeredByUserId,
    triggeredByUserName,
    triggeredByUserRole,
    details,
  } = params;

  // In-app notifications are a separate channel from email: they are raised
  // first and are NOT gated by the Super Admin's email toggle below, which
  // controls who receives *mail* about feature requests.
  void raiseInAppNotifications(params);

  try {
    const config = await getNotificationConfig();
    const { FeatureRequestNotificationLog } = getModels();

    // ── If notifications are globally disabled, log as skipped and return ──
    if (!config.enabled) {
      await FeatureRequestNotificationLog.create({
        featureRequestId,
        activityType,
        triggeredByUserId,
        triggeredByUserName,
        triggeredByUserRole,
        featureRequestTitle,
        recipients: [],
        subject: '',
        success: false,
        skipped: true,
      });
      return;
    }

    // ── If this specific activity type is toggled off, silently return ─────
    if (config.activities[activityType] === false) {
      return;
    }

    // ── If no recipients configured, silently return ───────────────────────
    if (!config.recipients || config.recipients.length === 0) {
      return;
    }

    // ── Build email subject ────────────────────────────────────────────────
    const label = ACTIVITY_LABELS[activityType] || 'Feature Request Update';
    const subject = `${label}: "${featureRequestTitle}"`;

    // ── Build template variables ───────────────────────────────────────────
    const appUrl = (process.env.FRONTEND_URL || 'https://app.mengoengine.com').replace(/\/+$/, '');
    const dashboardUrl = `${appUrl}/super-admin/feature-requests`;

    const variables: Record<string, string> = {
      activity_type: activityType,
      activity_label: label,
      request_title: featureRequestTitle,
      request_id: featureRequestId,
      triggered_by_name: triggeredByUserName,
      triggered_by_role: triggeredByUserRole,
      dashboard_url: dashboardUrl,
      app_url: appUrl,
      status: details?.status || '',
      previous_status: details?.previousStatus || '',
      admin_note: details?.adminNote || '',
      comment_content: details?.commentContent || '',
    };

    // ── Send email(s) ──────────────────────────────────────────────────────
    let overallSuccess = false;
    let lastError = '';
    let lastMessageId = '';

    for (const recipient of config.recipients) {
      try {
        const result = await sendNotificationEmail({
          to: recipient,
          template: 'feature-request-notification',
          subject,
          variables,
        });

        if (result.success) {
          overallSuccess = true;
          lastMessageId = result.messageId || '';
        } else {
          lastError = result.error || 'Unknown error';
        }
      } catch (mailErr: any) {
        lastError = mailErr?.message || 'Email send failed';
      }
    }

    // ── Log the result ─────────────────────────────────────────────────────
    await FeatureRequestNotificationLog.create({
      featureRequestId,
      activityType,
      triggeredByUserId,
      triggeredByUserName,
      triggeredByUserRole,
      featureRequestTitle,
      recipients: config.recipients,
      subject,
      success: overallSuccess,
      error: lastError || undefined,
      messageId: lastMessageId || undefined,
      skipped: false,
    });
  } catch (err: any) {
    // Never throw — log and swallow
    console.error('[FeatureRequestNotifications] notifyFeatureRequestActivity error:', err?.message);
  }
}