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

import { MODEL_NAMES } from './_models';

export interface ILoanSnapshot {
  loanProductId: mongoose.Types.ObjectId;
  effectiveDate: Date;
  source: string;
  balance: number;
  floatedBalance: number;
  statementBalance: number;
  charges: {
    chargeId: mongoose.Types.ObjectId;
    chargeName: string;
    amount: number;
    amountPaid: number;
  }[];
}

export type TLoanSnapshotDoc = mongoose.HydratedDocument<ILoanSnapshot>;

export interface ILoanSnapshotLean extends ILoanSnapshot {
  _id: mongoose.Types.ObjectId;
  createdAt: Date;
  updatedAt: Date;
}

export interface ILoanSnapshotPlain extends Omit<ILoanSnapshot, 'loanProductId' | 'charges'> {
  _id: string;
  loanProductId: string;
  charges: {
    chargeId: string;
    chargeName: string;
    amount: number;
    amountPaid: number;
  }[];
  createdAt: Date;
  updatedAt: Date;
}

const LoanSnapshotChargeCreateValidationSchema = Joi.object({
  chargeId: Joi.string().required(),
  chargeName: Joi.string().required(),
  amount: Joi.number().required(),
  amountPaid: Joi.number().required(),
});

const LoanSnapshotChargeUpdateValidationSchema = Joi.object({
  chargeId: Joi.string().required(),
  chargeName: Joi.string(),
  amount: Joi.number(),
  amountPaid: Joi.number(),
});

export const LoanSnapshotCreateValidationSchema = Joi.object({
  loanProductId: Joi.string().required(),
  effectiveDate: Joi.date().required(),
  source: Joi.string().required(),
  balance: Joi.number().required(),
  floatedBalance: Joi.number().required(),
  statementBalance: Joi.number().required(),
  charges: Joi.array()
    .items(LoanSnapshotChargeCreateValidationSchema)
    .required(),
});

export const LoanSnapshotUpdateValidationSchema = Joi.object({
  _id: Joi.string().required(),
  loanProductId: Joi.string(),
  effectiveDate: Joi.date(),
  source: Joi.string(),
  balance: Joi.number(),
  floatedBalance: Joi.number(),
  statementBalance: Joi.number(),
  charges: Joi.array().items(LoanSnapshotChargeUpdateValidationSchema),
});

export type TLoanSnapshotModel = mongoose.Model<ILoanSnapshot>;

export const LoanSnapshotSchema = new mongoose.Schema<ILoanSnapshot, TLoanSnapshotModel>(
  {
    loanProductId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.loanProducts,
      required: true,
    },
    effectiveDate: {
      type: Date,
      required: true,
    },
    source: {
      type: String,
      required: true,
    },
    balance: {
      type: Number,
      required: true,
    },
    floatedBalance: {
      type: Number,
      required: true,
    },
    statementBalance: {
      type: Number,
      required: true,
    },
    charges: [{
      chargeId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: MODEL_NAMES.loanCharges,
        required: true,
      },
      chargeName: {
        type: String,
        required: true,
      },
      amount: {
        type: Number,
        required: true,
      },
      amountPaid: {
        type: Number,
        required: true,
      },
    }],
  },
  {
    timestamps: { createdAt: true, updatedAt: true },
    versionKey: false,
  },
);

LoanSnapshotSchema.index(
  { loanProductId: 1, effectiveDate: 1 },
  { unique: true },
);

export const LoanSnapshot = mongoose.model<ILoanSnapshot, TLoanSnapshotModel>(MODEL_NAMES.loanSnapshots, LoanSnapshotSchema);
