import mongoose, { Schema, model, Document } from 'mongoose';
import Joi from 'joi';
import { MODEL_NAMES } from './_models';

export const CRMCalculationInputsValidationSchema = Joi.object<ICRMCalculationInputs>({
  primeRate: Joi.number().required(),
  leverageCost: Joi.number().required(),
  equityCost: Joi.number().required(),

  yearsRevolver: Joi.number().required(),
  yearsTerm: Joi.number().required(),

  commitmentRevolver: Joi.number().required(),
  commitmentTerm: Joi.number().required(),

  utilizationRevolver: Joi.number().required(),
  utilizationTerm: Joi.number().required(),

  marginRevolver: Joi.number().required(),
  marginTerm: Joi.number().required(),

  adminFeeRevolver: Joi.number().required(),
  adminFeeTerm: Joi.number().required(),

  closingPointsRevolver: Joi.number().required(),
  closingPointsTerm: Joi.number().required(),

  annualLineFeeRevolver: Joi.number().required(),
  annualLineFeeTerm: Joi.number().required(),

  unusedLineFee: Joi.number().required(),

  referralPointsRevolver: Joi.number().required(),
  referralPointsTerm: Joi.number().required(),

  referralPercentRevolver: Joi.number().required(),
  referralPercentTerm: Joi.number().required(),

  leveragePercentRevolver: Joi.number().required(),
  leveragePercentTerm: Joi.number().required(),
});

export interface ICRMCalculationInputs {
  primeRate: number;
  leverageCost: number;
  equityCost: number;

  yearsRevolver: number;
  yearsTerm: number;

  commitmentRevolver: number;
  commitmentTerm: number;

  utilizationRevolver: number;
  utilizationTerm: number;

  marginRevolver: number;
  marginTerm: number;

  adminFeeRevolver: number;
  adminFeeTerm: number;

  closingPointsRevolver: number;
  closingPointsTerm: number;

  annualLineFeeRevolver: number;
  annualLineFeeTerm: number;

  unusedLineFee: number;

  referralPointsRevolver: number;
  referralPointsTerm: number;

  referralPercentRevolver: number;
  referralPercentTerm: number;

  leveragePercentRevolver: number;
  leveragePercentTerm: number;
}

export interface ICRMCalculationResultsData {
  revolver: number;
  term: number;
  blended: number;
}

export const CRMYieldCalculationResultsKeys = [
  'margin',
  'outstanding',
  'interest',
  'adminFee',
  'closing',
  'annual',
  'unusedLineFee',
  'grossYield',
  'referralFeePoints',
  'referralFeePercent',
  'opYield',
  'costOfCapital',
  'netYield',
  'leveragedReturn',
  'leveragedMOIC',
  'impliedIRR',
] as const;

export type TCRMResultKey = typeof CRMYieldCalculationResultsKeys[number];

export type TCRMCalculationResults = {
  [K in TCRMResultKey]: ICRMCalculationResultsData
}

export interface ICRMCalculation {
  prospectId: mongoose.Schema.Types.ObjectId;
  inputs: ICRMCalculationInputs;
  results: TCRMCalculationResults;
}

export interface ICRMCalculationDoc extends ICRMCalculation, Document {
}

export const CRMCalculationInputsSchema = new Schema<ICRMCalculationInputs>({
  primeRate: { type: Number, required: true },
  leverageCost: { type: Number, required: true },
  equityCost: { type: Number, required: true },

  yearsTerm: { type: Number, required: true },
  yearsRevolver: { type: Number, required: true },

  commitmentRevolver: { type: Number, required: true },
  commitmentTerm: { type: Number, required: true },

  utilizationRevolver: { type: Number, required: true },
  utilizationTerm: { type: Number, required: true },

  marginRevolver: { type: Number, required: true },
  marginTerm: { type: Number, required: true },

  adminFeeRevolver: { type: Number, required: true },
  adminFeeTerm: { type: Number, required: true },

  closingPointsRevolver: { type: Number, required: true },
  closingPointsTerm: { type: Number, required: true },

  annualLineFeeRevolver: { type: Number, required: true },
  annualLineFeeTerm: { type: Number, required: true },

  unusedLineFee: { type: Number, required: true },

  referralPointsRevolver: { type: Number, required: true },
  referralPointsTerm: { type: Number, required: true },

  referralPercentRevolver: { type: Number, required: true },
  referralPercentTerm: { type: Number, required: true },

  leveragePercentRevolver: { type: Number, required: true },
  leveragePercentTerm: { type: Number, required: true },
}, { timestamps: false, versionKey: false, _id: false });

export const CRMCalculationResultsDataSchema = new Schema<ICRMCalculationResultsData>({
  revolver: { type: Number, required: true },
  term: { type: Number, required: true },
  blended: { type: Number, required: true },
}, { timestamps: false, versionKey: false, _id: false });

const resultFields = Object.fromEntries(
  CRMYieldCalculationResultsKeys.map((key) => [
    key,
    { type: CRMCalculationResultsDataSchema, required: true },
  ]),
);

export const CRMCalculationResultsSchema = new Schema<TCRMCalculationResults>(
  resultFields,
  { timestamps: false, versionKey: false, _id: false },
);

export const CRMCalculationSchema = new Schema<ICRMCalculation>({
  prospectId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: MODEL_NAMES.CRMProspects,
    required: true,
    index: true,
  },
  inputs: { type: CRMCalculationInputsSchema, required: true },
  results: { type: CRMCalculationResultsSchema, required: true },
}, { timestamps: true, versionKey: false });

export const CRMCalculationModel = model<ICRMCalculation>(MODEL_NAMES.CRMYieldCalculations, CRMCalculationSchema);
