import mongoose, { Model } from 'mongoose';

import { MODEL_NAMES } from './_models';

export interface IFinancialSpreadingAlias {
  sheetId: mongoose.Types.ObjectId;
  aliases: {
    original: string;
    normalized: string;
  }[];
}

export interface IFinancialSpreadingAliasDoc extends IFinancialSpreadingAlias, Document {
  _id: mongoose.Types.ObjectId;
  createdAt: Date;
  updatedAt: Date;
}

export interface IFinancialSpreadingAliasLean extends IFinancialSpreadingAlias {
  _id: mongoose.Types.ObjectId;
  createdAt: Date;
  updatedAt: Date;
}

export interface IFinancialSpreadingAliasPlain extends Omit<IFinancialSpreadingAlias, 'sheetId'> {
  _id: string;
  sheetId: string;
  createdAt: Date;
  updatedAt: Date;
}

export type TFinancialSpreadingAliasModel = Model<IFinancialSpreadingAlias>;

export const FinancialSpreadingAliasSchema = new mongoose.Schema<IFinancialSpreadingAlias, TFinancialSpreadingAliasModel>(
  {
    sheetId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.financialSpreadingSheets,
      required: true,
    },
    aliases: [{
      original: {
        type: String,
        required: false,
        trim: true,
      },
      normalized: {
        type: String,
        required: false,
        trim: true,
      },
    }],
  },
  {
    timestamps: { createdAt: true, updatedAt: true },
  },
);

export const FinancialSpreadingAlias = mongoose.model<IFinancialSpreadingAlias, TFinancialSpreadingAliasModel>(MODEL_NAMES.financialSpreadingAlias, FinancialSpreadingAliasSchema);

FinancialSpreadingAliasSchema.index({
  'aliases.normalized': 1,
});

FinancialSpreadingAliasSchema.pre('validate', function(next) {
  this.aliases = this.aliases
    .filter(a => a.original?.trim())
    .map(a => ({
      original: a.original.trim(),
      normalized: normalizeAlias(a.original),
    }));

  next();
});

export function normalizeAlias(input: string): string {
  return input
    .toLowerCase()
    .replace(/[–—−]/g, '-')
    .replace(/[_]/g, ' ')
    .replace(/[^\p{L}\p{N}\s-]/gu, '')
    .replace(/\s+/g, ' ')
    .trim();
}
