import mongoose, { Schema, Document, Model } from 'mongoose';
import type { FunnelDefinition } from '@/lib/funnel/types';

export interface IFunnelHistory extends Document {
  funnelId: string; // MongoDB ObjectId воронки
  sessionId: string; // Уникальный идентификатор сессии редактирования
  
  // Снимок данных воронки
  funnelSnapshot: FunnelDefinition;
  
  // Метаданные изменения
  actionType: 'create' | 'update' | 'save' | 'publish' | 'rollback';
  description?: string; // Описание изменения для пользователя
  
  // Техническая информация
  changeDetails?: {
    field?: string; // Какое поле изменено
    previousValue?: unknown; // Предыдущее значение
    newValue?: unknown; // Новое значение
    action?: string; // Тип операции (add-screen, update-screen, etc.)
  };
  
  // Пользователь и время
  createdBy?: string;
  createdAt: Date;
  
  // Позиция в истории
  sequenceNumber: number; // Порядковый номер в рамках сессии
  isBaseline: boolean; // Является ли базовой точкой (сохранено в БД)
}

const ChangeDetailsSchema = new Schema({
  field: String,
  previousValue: Schema.Types.Mixed,
  newValue: Schema.Types.Mixed,  
  action: String
}, { _id: false });

const FunnelHistorySchema = new Schema<IFunnelHistory>({
  funnelId: { 
    type: String,
    required: true,
    index: true
  },
  sessionId: { 
    type: String, 
    required: true,
    index: true
  },
  
  // Полный снимок данных воронки на момент изменения
  funnelSnapshot: { 
    type: Schema.Types.Mixed, 
    required: true 
  },
  
  // Метаданные
  actionType: { 
    type: String, 
    enum: ['create', 'update', 'save', 'publish', 'rollback'],
    required: true 
  },
  description: { 
    type: String,
    maxlength: 500
  },
  
  changeDetails: ChangeDetailsSchema,
  
  // Пользователь
  createdBy: String,
  
  // Позиция в истории
  sequenceNumber: { 
    type: Number, 
    required: true,
    min: 0
  },
  isBaseline: { 
    type: Boolean, 
    default: false 
  }
}, {
  timestamps: true,
  collection: 'funnel_history'
});

// Составной индекс для быстрого поиска истории сессии
FunnelHistorySchema.index({ 
  funnelId: 1, 
  sessionId: 1, 
  sequenceNumber: 1 
});

// Индекс для очистки старых записей
FunnelHistorySchema.index({ createdAt: 1 });

// Индекс для поиска базовых точек
FunnelHistorySchema.index({ 
  funnelId: 1, 
  isBaseline: 1, 
  createdAt: -1 
});

// Статические методы
FunnelHistorySchema.statics = {
  getSessionHistory: function(funnelId: string, sessionId: string, limit: number = 50) {
    return this.find({ 
      funnelId, 
      sessionId 
    })
    .sort({ sequenceNumber: -1 })
    .limit(limit);
  },

  getLatestBaseline: function(funnelId: string) {
    return this.findOne({ 
      funnelId, 
      isBaseline: true 
    })
    .sort({ createdAt: -1 });
  },

  createHistoryEntry: function(
    funnelId: string,
    sessionId: string,
    funnelSnapshot: FunnelDefinition,
    actionType: string,
    sequenceNumber: number,
    options?: {
      description?: string;
      changeDetails?: unknown;
      createdBy?: string;
      isBaseline?: boolean;
    }
  ) {
    return this.create({
      funnelId,
      sessionId,
      funnelSnapshot,
      actionType,
      sequenceNumber,
      description: options?.description,
      changeDetails: options?.changeDetails,
      createdBy: options?.createdBy,
      isBaseline: options?.isBaseline || false
    });
  },

  // Автоматическая очистка старых записей (сохраняем только последние 100 записей на сессию)
  cleanupOldEntries: async function(funnelId: string, sessionId: string) {
    const KEEP_ENTRIES = 100;
    
    const entries = await this.find({ 
      funnelId, 
      sessionId 
    })
    .sort({ sequenceNumber: -1 })
    .skip(KEEP_ENTRIES)
    .select('_id');
    
    if (entries.length > 0) {
      const idsToDelete = entries.map((entry: { _id: unknown }) => entry._id);
      await this.deleteMany({ _id: { $in: idsToDelete } });
    }
  }
};

// Методы модели
FunnelHistorySchema.methods.toPublicJSON = function() {
  return {
    _id: this._id,
    actionType: this.actionType,
    description: this.description,
    sequenceNumber: this.sequenceNumber,
    isBaseline: this.isBaseline,
    createdAt: this.createdAt,
    changeDetails: this.changeDetails
  };
};

// Pre-save хук для валидации
FunnelHistorySchema.pre('save', function(next) {
  // Валидируем что funnelSnapshot имеет правильную структуру
  if (!this.funnelSnapshot || !this.funnelSnapshot.meta || !this.funnelSnapshot.screens) {
    return next(new Error('funnelSnapshot must contain meta and screens'));
  }
  
  next();
});

const FunnelHistoryModel: Model<IFunnelHistory> = 
  mongoose.models.FunnelHistory || 
  mongoose.model<IFunnelHistory>('FunnelHistory', FunnelHistorySchema);

export default FunnelHistoryModel;
