/**
 * Loyalty Programme Model
 * Comprehensive loyalty programme management with tiers, earn/redemption rules, rewards, and member tracking
 */

import mongoose, { Schema, Document } from 'mongoose';

// ============================================
// TYPE DEFINITIONS
// ============================================

export type LoyaltyType = 'points-based' | 'tiered' | 'cashback' | 'punch-card' | 'coalition' | 'hybrid' | 'custom';
export type LoyaltyStatus = 'draft' | 'active' | 'paused' | 'archived';
export type EarnTrigger = 'purchase' | 'action' | 'referral' | 'social-share' | 'review' | 'birthday' | 'anniversary' | 'signup' | 'milestone';
export type EarnCalculation = 'fixed' | 'percentage' | 'multiplier' | 'custom';
export type RedeemType = 'discount' | 'product' | 'voucher' | 'experience' | 'cash-equivalent' | 'donation' | 'upgrade';
export type RewardType = 'discount' | 'free-product' | 'upgrade' | 'experience' | 'gift-card' | 'donation' | 'voucher';
export type RewardStatus = 'draft' | 'active' | 'sold-out' | 'archived';
export type ChannelType = 'pos' | 'ecommerce' | 'mobile-app' | 'kiosk' | 'web';

// ============================================
// SUB-SCHEMA INTERFACES
// ============================================

export interface ITierBenefit {
  id: string;
  name: string;
  description?: string;
  type: 'discount' | 'free-shipping' | 'priority-support' | 'exclusive-access' | 'bonus-points' | 'perk' | 'custom';
  value?: number;
  unit?: 'percentage' | 'fixed' | 'points' | 'item';
}

export interface ILoyaltyTier {
  id: string;
  name: string;
  level: number;
  minPoints: number;
  maxPoints?: number;
  colour?: string;
  icon?: string;
  description?: string;
  descriptionVersions?: IDescriptionVersion[];
  benefits: ITierBenefit[];
  earnMultiplier: number;
  perks?: string[];
  badgeUrl?: string;
}

export interface IEarnCondition {
  minPurchase?: number;
  maxPurchase?: number;
  categories?: string[];
  products?: string[];
  channels?: ChannelType[];
  userSegments?: string[];
  firstTimeOnly?: boolean;
}

export interface IEarnCap {
  daily?: number;
  weekly?: number;
  monthly?: number;
  perTransaction?: number;
}

export interface IEarnRule {
  id: string;
  name: string;
  description?: string;
  descriptionVersions?: IDescriptionVersion[];
  trigger: EarnTrigger;
  calculation: EarnCalculation;
  value: number;
  conditions?: IEarnCondition;
  cap?: IEarnCap;
  active: boolean;
  priority?: number;
  startDate?: Date;
  endDate?: Date;
}

export interface IRedeemCondition {
  minTier?: string;
  maxPerMonth?: number;
  minPointsBalance?: number;
  availableFrom?: Date;
  availableUntil?: Date;
  categories?: string[];
}

export interface IRedeemRule {
  id: string;
  name: string;
  description?: string;
  descriptionVersions?: IDescriptionVersion[];
  type: RedeemType;
  pointsCost: number;
  value?: number;
  valueUnit?: 'percentage' | 'fixed' | 'item';
  productId?: string;
  conditions?: IRedeemCondition;
  active: boolean;
  startDate?: Date;
  endDate?: Date;
}

export interface ILoyaltyReward {
  id: string;
  name: string;
  description?: string;
  descriptionVersions?: IDescriptionVersion[];
  type: RewardType;
  pointsRequired: number;
  cashValue?: number;
  imageUrl?: string;
  quantity?: number;
  claimed?: number;
  terms?: string;
  availableFrom?: Date;
  availableUntil?: Date;
  tierRestrictions?: string[];
  status: RewardStatus;
  featured?: boolean;
}

export interface IPointsExpirySettings {
  enabled: boolean;
  months: number;
  warningDays: number;
}

export interface ITierDowngradeSettings {
  enabled: boolean;
  period: 'yearly' | 'quarterly' | 'monthly';
  retainPercentage: number;
}

export interface IPointsTransferSettings {
  enabled: boolean;
  fee?: number;
  minAmount?: number;
  maxAmount?: number;
}

export interface IVelocityRules {
  maxTransactionsPerHour: number;
  maxPointsPerHour: number;
  maxTransactionsPerDay: number;
  maxPointsPerDay: number;
}

export interface IFraudPreventionSettings {
  maxPointsPerDay: number;
  velocityRules: IVelocityRules;
  suspiciousActivityThreshold: number;
}

export interface IIntegrationSettings {
  channels: ChannelType[];
  posProvider?: string;
  posApiKey?: string;
  ecommercePlatform?: string;
  ecommerceWebhookUrl?: string;
  crmLink?: string;
  emailProvider?: string;
}

export interface ILoyaltySettings {
  pointsExpiry: IPointsExpirySettings;
  tierDowngrade: ITierDowngradeSettings;
  pointsTransfer: IPointsTransferSettings;
  fraudPrevention: IFraudPreventionSettings;
  integrations?: IIntegrationSettings;
  currency: string;
  pointsName: string;
  pointsPerCurrency: number;
}

export type NotificationType = 'points-earned' | 'points-expiring' | 'tier-upgrade' | 'tier-downgrade' | 'reward-available' | 'milestone' | 'welcome' | 'birthday';

export interface INotificationTemplate {
  email?: string;
  sms?: string;
  push?: string;
  inApp?: string;
}

export interface ILoyaltyNotification {
  id: string;
  type: NotificationType;
  template: INotificationTemplate;
  triggers: string[];
  active: boolean;
}

export interface IMonthlyPointsData {
  month: string;
  earned: number;
  redeemed: number;
  expired: number;
}

export interface ILoyaltyMetrics {
  totalMembers: number;
  activeMembers: number;
  newMembersThisMonth: number;
  tierDistribution: Record<string, number>;
  pointsIssued: number;
  pointsRedeemed: number;
  pointsExpired: number;
  redemptionRate: number;
  averagePointsPerMember: number;
  monthlyData: IMonthlyPointsData[];
}

// ============================================
// MAIN INTERFACE
// ============================================

export interface ILoyaltyProgramme extends Document {
  // A. Core Information
  name: string;
  description?: string;
  type: LoyaltyType;
  status: LoyaltyStatus;
  startDate?: Date;
  endDate?: Date;

  // B. Tier System
  tiers: ILoyaltyTier[];
  defaultTierId?: string;

  // C. Earn Rules
  earnRules: IEarnRule[];
  baseEarnRate?: number;

  // D. Redemption Rules
  redeemRules: IRedeemRule[];

  // E. Rewards Catalog
  rewards: ILoyaltyReward[];

  // F. Settings
  settings: ILoyaltySettings;

  // G. Notifications
  notifications?: ILoyaltyNotification[];

  // H. AI Generation
  aiGenerated?: boolean;
  aiPrompt?: string;

  // Hb. Description Version History
  descriptionVersions?: IDescriptionVersion[];

  // I. Documents
  termsConditions?: string;
  privacyPolicy?: string;
  faqDocument?: string;
  fullDocument?: string;

  // J. Branding
  programmeLogo?: string;
  primaryColour?: string;
  secondaryColour?: string;

  // K. Stats
  stats?: ILoyaltyMetrics;

  // L. Company Reference
  companyId: string;

  // Timestamps
  createdAt: Date;
  updatedAt: Date;
}

// ============================================
// DESCRIPTION VERSION SUB-SCHEMA
// ============================================

interface IDescriptionVersion {
  id: string;
  content: string;
  tone?: string;
  customInstructions?: string;
  generatedAt: Date;
  isCurrent?: boolean;
}

const DescriptionVersionSchema = new Schema<IDescriptionVersion>({
  id: { type: String, required: true },
  content: { type: String, required: true },
  tone: String,
  customInstructions: String,
  generatedAt: { type: Date, default: Date.now },
  isCurrent: { type: Boolean, default: false }
}, { _id: false });

// ============================================
// SUB-SCHEMAS
// ============================================

const TierBenefitSchema = new Schema<ITierBenefit>({
  id: { type: String, required: true },
  name: { type: String, required: true },
  description: String,
  type: {
    type: String,
    enum: ['discount', 'free-shipping', 'priority-support', 'exclusive-access', 'bonus-points', 'perk', 'custom'],
    required: true
  },
  value: Number,
  unit: { type: String, enum: ['percentage', 'fixed', 'points', 'item'] }
}, { _id: false });

const LoyaltyTierSchema = new Schema<ILoyaltyTier>({
  id: { type: String, required: true },
  name: { type: String, required: true },
  level: { type: Number, required: true },
  minPoints: { type: Number, required: true },
  maxPoints: Number,
  colour: String,
  icon: String,
  description: String,
  descriptionVersions: [DescriptionVersionSchema],
  benefits: [TierBenefitSchema],
  earnMultiplier: { type: Number, default: 1 },
  perks: [String],
  badgeUrl: String
}, { _id: false });

const EarnConditionSchema = new Schema<IEarnCondition>({
  minPurchase: Number,
  maxPurchase: Number,
  categories: [String],
  products: [String],
  channels: [{ type: String, enum: ['pos', 'ecommerce', 'mobile-app', 'kiosk', 'web'] }],
  userSegments: [String],
  firstTimeOnly: Boolean
}, { _id: false });

const EarnCapSchema = new Schema<IEarnCap>({
  daily: Number,
  weekly: Number,
  monthly: Number,
  perTransaction: Number
}, { _id: false });

const EarnRuleSchema = new Schema<IEarnRule>({
  id: { type: String, required: true },
  name: { type: String, required: true },
  description: String,
  descriptionVersions: [DescriptionVersionSchema],
  trigger: {
    type: String,
    enum: ['purchase', 'action', 'referral', 'social-share', 'review', 'birthday', 'anniversary', 'signup', 'milestone'],
    required: true
  },
  calculation: {
    type: String,
    enum: ['fixed', 'percentage', 'multiplier', 'custom'],
    required: true
  },
  value: { type: Number, required: true },
  conditions: EarnConditionSchema,
  cap: EarnCapSchema,
  active: { type: Boolean, default: true },
  priority: Number,
  startDate: Date,
  endDate: Date
}, { _id: false });

const RedeemConditionSchema = new Schema<IRedeemCondition>({
  minTier: String,
  maxPerMonth: Number,
  minPointsBalance: Number,
  availableFrom: Date,
  availableUntil: Date,
  categories: [String]
}, { _id: false });

const RedeemRuleSchema = new Schema<IRedeemRule>({
  id: { type: String, required: true },
  name: { type: String, required: true },
  description: String,
  descriptionVersions: [DescriptionVersionSchema],
  type: {
    type: String,
    enum: ['discount', 'product', 'voucher', 'experience', 'cash-equivalent', 'donation', 'upgrade'],
    required: true
  },
  pointsCost: { type: Number, required: true },
  value: Number,
  valueUnit: { type: String, enum: ['percentage', 'fixed', 'item'] },
  productId: String,
  conditions: RedeemConditionSchema,
  active: { type: Boolean, default: true },
  startDate: Date,
  endDate: Date
}, { _id: false });

const LoyaltyRewardSchema = new Schema<ILoyaltyReward>({
  id: { type: String, required: true },
  name: { type: String, required: true },
  description: String,
  descriptionVersions: [DescriptionVersionSchema],
  type: {
    type: String,
    enum: ['discount', 'free-product', 'upgrade', 'experience', 'gift-card', 'donation', 'voucher'],
    required: true
  },
  pointsRequired: { type: Number, required: true },
  cashValue: Number,
  imageUrl: String,
  quantity: Number,
  claimed: { type: Number, default: 0 },
  terms: String,
  availableFrom: Date,
  availableUntil: Date,
  tierRestrictions: [String],
  status: {
    type: String,
    enum: ['draft', 'active', 'sold-out', 'archived'],
    default: 'draft'
  },
  featured: { type: Boolean, default: false }
}, { _id: false });

const PointsExpirySettingsSchema = new Schema<IPointsExpirySettings>({
  enabled: { type: Boolean, default: false },
  months: { type: Number, default: 12 },
  warningDays: { type: Number, default: 30 }
}, { _id: false });

const TierDowngradeSettingsSchema = new Schema<ITierDowngradeSettings>({
  enabled: { type: Boolean, default: false },
  period: { type: String, enum: ['yearly', 'quarterly', 'monthly'], default: 'yearly' },
  retainPercentage: { type: Number, default: 0 }
}, { _id: false });

const PointsTransferSettingsSchema = new Schema<IPointsTransferSettings>({
  enabled: { type: Boolean, default: false },
  fee: Number,
  minAmount: Number,
  maxAmount: Number
}, { _id: false });

const VelocityRulesSchema = new Schema<IVelocityRules>({
  maxTransactionsPerHour: { type: Number, default: 10 },
  maxPointsPerHour: { type: Number, default: 1000 },
  maxTransactionsPerDay: { type: Number, default: 50 },
  maxPointsPerDay: { type: Number, default: 5000 }
}, { _id: false });

const FraudPreventionSettingsSchema = new Schema<IFraudPreventionSettings>({
  maxPointsPerDay: { type: Number, default: 10000 },
  velocityRules: { type: VelocityRulesSchema, default: () => ({}) },
  suspiciousActivityThreshold: { type: Number, default: 50000 }
}, { _id: false });

const IntegrationSettingsSchema = new Schema<IIntegrationSettings>({
  channels: [{ type: String, enum: ['pos', 'ecommerce', 'mobile-app', 'kiosk', 'web'] }],
  posProvider: String,
  posApiKey: String,
  ecommercePlatform: String,
  ecommerceWebhookUrl: String,
  crmLink: String,
  emailProvider: String
}, { _id: false });

const LoyaltySettingsSchema = new Schema<ILoyaltySettings>({
  pointsExpiry: { type: PointsExpirySettingsSchema, default: () => ({}) },
  tierDowngrade: { type: TierDowngradeSettingsSchema, default: () => ({}) },
  pointsTransfer: { type: PointsTransferSettingsSchema, default: () => ({}) },
  fraudPrevention: { type: FraudPreventionSettingsSchema, default: () => ({}) },
  integrations: IntegrationSettingsSchema,
  currency: { type: String, default: 'USD' },
  pointsName: { type: String, default: 'Points' },
  pointsPerCurrency: { type: Number, default: 1 }
}, { _id: false });

const NotificationTemplateSchema = new Schema<INotificationTemplate>({
  email: String,
  sms: String,
  push: String,
  inApp: String
}, { _id: false });

const LoyaltyNotificationSchema = new Schema<ILoyaltyNotification>({
  id: { type: String, required: true },
  type: {
    type: String,
    enum: ['points-earned', 'points-expiring', 'tier-upgrade', 'tier-downgrade', 'reward-available', 'milestone', 'welcome', 'birthday'],
    required: true
  },
  template: { type: NotificationTemplateSchema, default: () => ({}) },
  triggers: [String],
  active: { type: Boolean, default: true }
}, { _id: false });

const MonthlyPointsDataSchema = new Schema<IMonthlyPointsData>({
  month: { type: String, required: true },
  earned: { type: Number, default: 0 },
  redeemed: { type: Number, default: 0 },
  expired: { type: Number, default: 0 }
}, { _id: false });

const LoyaltyMetricsSchema = new Schema<ILoyaltyMetrics>({
  totalMembers: { type: Number, default: 0 },
  activeMembers: { type: Number, default: 0 },
  newMembersThisMonth: { type: Number, default: 0 },
  tierDistribution: { type: Schema.Types.Mixed, default: {} },
  pointsIssued: { type: Number, default: 0 },
  pointsRedeemed: { type: Number, default: 0 },
  pointsExpired: { type: Number, default: 0 },
  redemptionRate: { type: Number, default: 0 },
  averagePointsPerMember: { type: Number, default: 0 },
  monthlyData: [MonthlyPointsDataSchema]
}, { _id: false });

// ============================================
// MAIN SCHEMA
// ============================================

const LoyaltyProgrammeSchema = new Schema<ILoyaltyProgramme>({
  // A. Core Information
  name: {
    type: String,
    required: [true, 'Programme name is required'],
    trim: true,
    maxlength: [200, 'Programme name cannot exceed 200 characters']
  },
  description: { type: String, trim: true },
  type: {
    type: String,
    enum: ['points-based', 'tiered', 'cashback', 'punch-card', 'coalition', 'hybrid', 'custom'],
    required: [true, 'Programme type is required'],
    default: 'points-based'
  },
  status: {
    type: String,
    enum: ['draft', 'active', 'paused', 'archived'],
    default: 'draft'
  },
  startDate: Date,
  endDate: Date,

  // B. Tier System
  tiers: [LoyaltyTierSchema],
  defaultTierId: String,

  // C. Earn Rules
  earnRules: [EarnRuleSchema],
  baseEarnRate: { type: Number, default: 1 },

  // D. Redemption Rules
  redeemRules: [RedeemRuleSchema],

  // E. Rewards Catalog
  rewards: [LoyaltyRewardSchema],

  // F. Settings
  settings: { type: LoyaltySettingsSchema, default: () => ({}) },

  // G. Notifications
  notifications: [LoyaltyNotificationSchema],

  // H. AI Generation
  aiGenerated: { type: Boolean, default: false },
  aiPrompt: String,

  // Hb. Description Version History
  descriptionVersions: [DescriptionVersionSchema],

  // I. Documents
  termsConditions: String,
  privacyPolicy: String,
  faqDocument: String,
  fullDocument: String,

  // J. Branding
  programmeLogo: String,
  primaryColour: String,
  secondaryColour: String,

  // K. Stats
  stats: LoyaltyMetricsSchema,

  // L. Company Reference
  companyId: {
    type: String,
    required: [true, 'Company ID is required'],
    index: true
  }

}, {
  timestamps: true
});

// ============================================
// INDEXES
// ============================================

LoyaltyProgrammeSchema.index({ companyId: 1, status: 1 });
LoyaltyProgrammeSchema.index({ companyId: 1, type: 1 });
LoyaltyProgrammeSchema.index({ companyId: 1, startDate: 1, endDate: 1 });

// ============================================
// EXPORT
// ============================================

export const LoyaltyProgramme = mongoose.model<ILoyaltyProgramme>('LoyaltyProgramme', LoyaltyProgrammeSchema);