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

import { ISelectedMonth } from '../helpers/date.helper';
import { MODEL_NAMES } from './_models';
import { ILoanChargeLean } from './LoanCharges.model';
import { ILoanProductLean } from './LoanProducts.model';

export const yieldParamsValidationSchema = Joi.object<IYieldParams>({
  periodStart: Joi.object({
    month: Joi.number().integer().min(1).max(12),
    year: Joi.number().integer().min(1900).max(9999),
  }),
  periodEnd: Joi.object({
    month: Joi.number().integer().min(1).max(12),
    year: Joi.number().integer().min(1900).max(9999),
  }),
  forLifetime: Joi.boolean(),
  ignoreOldData: Joi.boolean(),
});

export enum ETotalType {
  AVERAGE_BALANCE = 'AVERAGE_BALANCE',
  AVERAGE_LIFE_BALANCE = 'AVERAGE_LIFE_BALANCE',
  BROKER = 'BROKER',
  GROSS = 'GROSS',
  NET = 'NET',
  APR = 'APR',
  APR_GROSS = 'APR_GROSS',
  APR_LIFE_GROSS = 'APR_LIFE_GROSS',
}

export const YIELD_TOTALS_MAP: Record<
  ETotalType,
  {
    order: number;
    title: string;
    class: string;
  }
> = {
  [ETotalType.AVERAGE_BALANCE]: { order: -2, title: 'Average Balance in Month $', class: 'whiteOnOrange' },
  [ETotalType.AVERAGE_LIFE_BALANCE]: { order: -1, title: 'Average loan life balance $', class: 'whiteOnOrange' },
  [ETotalType.GROSS]: { order: 1, title: 'Gross income $', class: 'whiteOnGray' },
  [ETotalType.BROKER]: { order: 2, title: 'Broker Fees $', class: 'whiteOnGray' },
  [ETotalType.NET]: { order: 3, title: 'Net income $', class: 'whiteOnGray' },
  [ETotalType.APR]: { order: 5, title: 'Yield APR', class: 'whiteOnGray' },
  [ETotalType.APR_GROSS]: { order: 6, title: 'Yield in month', class: 'whiteOnBlack' },
  [ETotalType.APR_LIFE_GROSS]: { order: 7, title: 'Yield since inception', class: 'whiteOnBlack' },
};

export interface IYieldParams {
  periodStart?: ISelectedMonth;
  periodEnd?: ISelectedMonth;
  forLifetime?: boolean;
  ignoreOldData?: boolean;
}

export interface IYieldData {
  productId?: mongoose.Types.ObjectId;
  chargeId?: mongoose.Types.ObjectId;
  totalType: string;
  year: number;
  month: number;
  value?: number;
  valuePercent?: number;
}

export interface IYieldViewData {
  order: number;
  charge: ILoanChargeLean;
  product: ILoanProductLean;
  title: string;
  class?: string;

  [key: `value-${string}`]: number | string | ILoanChargeLean | ILoanProductLean;
  [key: `valuePercent-${string}`]: number | string | ILoanChargeLean | ILoanProductLean;
}

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

export interface IYieldDataLean extends IYieldData {
  _id: mongoose.Types.ObjectId;
  createdAt: Date;
  updatedAt: Date;
}

export interface IYieldDataPlain extends Omit<IYieldData, 'productId' | 'chargeId'> {
  _id: string;
  productId: string;
  chargeId: string;
}

export type TYieldDataModel = mongoose.Model<IYieldData>;

export const YieldDataSchema = new mongoose.Schema<IYieldData, TYieldDataModel>(
  {
    productId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.loanProducts,
      required: false,
    },
    chargeId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.loanCharges,
      required: false,
    },
    totalType: {
      type: String,
    },
    year: {
      type: Number,
      required: true,
    },
    month: {
      type: Number,
      required: true,
    },
    value: {
      type: Number,
    },
    valuePercent: {
      type: Number,
    },
  },
  {
    timestamps: { createdAt: false, updatedAt: false },
  },
);

export const YieldData = mongoose.model<IYieldData, TYieldDataModel>(MODEL_NAMES.yieldData, YieldDataSchema);
