/**
 * Platform referral settings.
 *
 * Referral configuration used to be per company, edited from Referral
 * Management → Settings. It is now owned by Super Admin and applies platform
 * wide: one document, one place to change it, read by every part of the referral
 * system.
 *
 * The existing `ReferralTrackingSettings` model and its existing fields are
 * reused unchanged — nothing about the shape of the settings changed, only who
 * owns them and how many copies exist. The single platform document is stored
 * under a reserved `companyId` sentinel so the model needed no schema change
 * (companyId is required and uniquely indexed, which conveniently guarantees
 * there can only ever be ONE platform row).
 *
 * On first read the platform document is seeded from the most recently updated
 * existing company document when there is one, so an installation that had
 * already configured referral settings keeps those values through the move
 * rather than silently reverting to defaults.
 */

import { getModels } from '../models';

/**
 * Reserved `companyId` of the single platform-wide settings document. Not a real
 * company id, and the leading underscores keep it clear of any generated id.
 */
export const PLATFORM_REFERRAL_SETTINGS_ID = '__platform__';

/** The fields Super Admin may set — the same list the module's own editor used. */
export const REFERRAL_SETTINGS_FIELDS = [
  'defaultReferrerReward',
  'defaultRefereeReward',
  'referralCodePrefix',
  'referralLinkBaseUrl',
  'autoApprove',
  'requireEmailVerification',
  'reminderFrequencyDays',
  'maxReminders',
  'expiryDays',
  'notifications',
] as const;

/** Defaults, matching what the per-company endpoint created before the move. */
function defaultSettings() {
  return {
    companyId: PLATFORM_REFERRAL_SETTINGS_ID,
    referralCodePrefix: 'REF',
    referralLinkBaseUrl: '',
    defaultReferrerReward: { type: 'credit', value: 50, valueType: 'fixed' },
    defaultRefereeReward: { type: 'discount', value: 10, valueType: 'percentage' },
    autoApprove: true,
    requireEmailVerification: true,
    reminderFrequencyDays: 7,
    maxReminders: 3,
    expiryDays: 30,
    notifications: {
      onRegistration: true,
      onSubscriptionPurchase: true,
      onRewardEarned: true,
    },
  };
}

/**
 * The platform referral settings, creating them on first access.
 *
 * Never throws: referral flows call this on paths where a settings problem must
 * not break the operation (creating a referral, sending a notification), so a
 * failure resolves to null and the caller falls back to its own default, exactly
 * as it did when a company had no settings document.
 */
export async function getPlatformReferralSettings(): Promise<any | null> {
  try {
    const { ReferralTrackingSettings } = getModels();

    const existing = await ReferralTrackingSettings.findOne({ companyId: PLATFORM_REFERRAL_SETTINGS_ID });
    if (existing) return existing;

    // First access. Carry over a company's existing configuration if there is
    // one, so the values that were already in use survive the move to Super Admin.
    const seed = await ReferralTrackingSettings
      .findOne({ companyId: { $ne: PLATFORM_REFERRAL_SETTINGS_ID } })
      .sort({ updatedAt: -1 })
      .lean();

    const base: any = defaultSettings();
    if (seed) {
      for (const field of REFERRAL_SETTINGS_FIELDS) {
        if ((seed as any)[field] !== undefined) base[field] = (seed as any)[field];
      }
      console.log('[ReferralSettings] Seeded platform referral settings from an existing company configuration.');
    }

    return await ReferralTrackingSettings.create(base);
  } catch (error: any) {
    console.error('[ReferralSettings] Failed to read platform referral settings:', error?.message);
    return null;
  }
}

/** Apply a Super Admin edit to the single platform document. */
export async function updatePlatformReferralSettings(body: Record<string, any>): Promise<any> {
  const { ReferralTrackingSettings } = getModels();

  // Ensure the document exists (and is seeded) before patching it.
  await getPlatformReferralSettings();

  const updateData: Record<string, any> = {};
  for (const field of REFERRAL_SETTINGS_FIELDS) {
    if (body[field] !== undefined) updateData[field] = body[field];
  }

  return ReferralTrackingSettings.findOneAndUpdate(
    { companyId: PLATFORM_REFERRAL_SETTINGS_ID },
    { $set: updateData },
    { new: true, upsert: true, setDefaultsOnInsert: true },
  );
}
