import mongoose from 'mongoose';
import Joi from 'joi';

import { EChargeCalculationBasis, EChargeFrequencies } from '../enums/loan-types.enum';
import { ELoanChargeType } from '../enums/loan-charge-type.enum';
import { MODEL_NAMES } from './_models';

export const chargeViewValidationSchema = Joi.object<ILoanChargeView & { valid: boolean }>({
  valid: Joi.boolean(),
  _id: Joi.string().allow(null),
  active: Joi.boolean(),
  name: Joi.string().required(),
  code: Joi.string().required(),
  PLCode: Joi.string().required(),
  productId: Joi.string().required(),
  percent: Joi.number().required().min(0),
  minimumAmount: Joi.number().required().min(0),
  frequency: Joi.string().required().valid(...Object.keys(EChargeFrequencies)),
  applyFrom: Joi.date().required(),
  calculationBasis: Joi.string().required().valid(...Object.keys(EChargeCalculationBasis)),
  chargeType: Joi.string().required().valid(...Object.keys(ELoanChargeType)),
  includeInYield: Joi.boolean().required(),
  paymentOrder: Joi.number(),
});

export interface ILoanCharge {
  borrowerId: mongoose.Types.ObjectId;
  order: number;
  active: boolean;
  name: string;
  code: string;
  PLCode: string,
  productId: mongoose.Types.ObjectId;
  percent: number;
  minimumAmount: number;
  frequency: EChargeFrequencies;
  applyFrom: Date;
  calculationBasis: EChargeCalculationBasis;
  chargeType: ELoanChargeType;
  deletedAt?: Date;
  paymentOrder?: number;
  includeInYield: boolean;
}

export interface ILoanChargeWithId extends ILoanCharge {
  _id: mongoose.Types.ObjectId;
}

export type ILoanChargeView = Omit<ILoanChargeWithId, 'borrowerId' | 'order'>

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

export interface ILoanChargeLean extends ILoanCharge {
  _id: mongoose.Types.ObjectId;
  createdAt: Date;
  updatedAt: Date;
}

export interface ILoanChargePlain extends Omit<ILoanCharge, 'borrowerId' | 'productId'> {
  _id: string;
  borrowerId: string;
  productId: string;
}

export type TLoanChargeModel = mongoose.Model<ILoanCharge>;

export const defaultChargeList: ILoanChargeView[] = [
  {
    _id: null,
    active: true,
    name: 'Interest',
    code: ELoanChargeType.INTEREST_FEE,
    PLCode: '',
    chargeType: ELoanChargeType.INTEREST_FEE,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.DAILY,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.DAILY_BALANCE,
    includeInYield: false,
  },
  {
    _id: null,
    active: true,
    name: 'Admin Fees',
    code: ELoanChargeType.ADMIN_FEE,
    PLCode: '',
    chargeType: ELoanChargeType.ADMIN_FEE,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.MONTHLY,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.AVERAGE_MONTHLY_BALANCE,
    includeInYield: false,
  },
  {
    _id: null,
    active: true,
    name: 'Unused Line Fee',
    code: ELoanChargeType.UNUSED_LINE_FEE,
    PLCode: '',
    chargeType: ELoanChargeType.UNUSED_LINE_FEE,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.DAILY,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.UNUSED_AMOUNT,
    includeInYield: false,
  },
  {
    _id: null,
    active: true,
    name: 'Annual Line Fee',
    code: ELoanChargeType.ANNUAL_LINE_FEE,
    PLCode: '',
    chargeType: ELoanChargeType.ANNUAL_LINE_FEE,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.ANNUAL,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.COMMITMENT,
    includeInYield: false,
  },
  {
    _id: null,
    active: true,
    name: 'Wire Fee',
    code: ELoanChargeType.WIRE_FEE,
    PLCode: '',
    chargeType: ELoanChargeType.WIRE_FEE,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.DISBURSEMENT,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.DISBURSEMENT_AMOUNT,
    includeInYield: false,
  },
  {
    _id: null,
    active: true,
    name: 'Forbearance',
    code: ELoanChargeType.OTHER,
    PLCode: '',
    chargeType: ELoanChargeType.OTHER,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.ONE_TIME,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.FIXED,
    includeInYield: false,
  },
  {
    _id: null,
    active: true,
    name: 'Overline/Over-advance',
    code: ELoanChargeType.OTHER,
    PLCode: '',
    chargeType: ELoanChargeType.OTHER,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.ONE_TIME,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.FIXED,
    includeInYield: false,
  },
  {
    _id: null,
    active: true,
    name: 'Closing Points',
    code: ELoanChargeType.OTHER,
    PLCode: '',
    chargeType: ELoanChargeType.OTHER,
    productId: null,
    percent: 0,
    minimumAmount: 0,
    frequency: EChargeFrequencies.ONE_TIME,
    applyFrom: null,
    calculationBasis: EChargeCalculationBasis.FIXED,
    includeInYield: false,
  },
];

export const LoanChargeSchema = new mongoose.Schema(
  {
    borrowerId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowers,
      required: true,
    },
    order: {
      type: Number,
      required: true,
    },
    active: {
      type: Boolean,
      required: true,
    },
    name: {
      type: String,
      required: true,
      trim: true,
    },
    code: {
      type: String,
      required: true,
      trim: true,
    },
    PLCode: {
      type: String,
      required: true,
      trim: true,
    },
    productId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.loanProducts,
      required: true,
    },
    percent: {
      type: Number,
      required: true,
    },
    minimumAmount: {
      type: Number,
      required: true,
    },
    frequency: {
      type: String,
      required: true,
      trim: true,
    },
    applyFrom: {
      type: Date,
      required: true,
    },
    calculationBasis: {
      type: String,
      required: true,
      trim: true,
    },
    chargeType: {
      type: String,
      required: true,
      trim: true,
    },
    includeInYield: {
      type: Boolean,
      required: true,
    },
    deletedAt: {
      type: Date,
    },
    paymentOrder: {
      type: Number,
    },
    __v: { type: Number, select: false },
  },
  { timestamps: true },
);

export const LoanCharge = mongoose.model<ILoanChargeDoc>(MODEL_NAMES.loanCharges, LoanChargeSchema);
