import mongoose, { Document } from 'mongoose';

import { IBorrowerDataDocWithName } from './BorrowerData.model';
import { IBorrowerDataContactDoc } from './BorrowerDataContact.model';
import { IBorrowerDataGuaranteeDoc } from './BorrowerDataGuarantee.model';
import { IBorrowerDataLocationDoc } from './BorrowerDataLocation.model';
import { IBorrowerDataBankDoc } from './BorrowerDataBank.model';
import { IBorrowerDataInsuranceDoc } from './BorrowerDataInsurance.model';
import { IBorrowerDataReceivableDoc } from './BorrowerDataReceivable.model';
import { IBorrowerDataInventoryDoc } from './BorrowerDataInventory.model';
import { IBorrowerDataTermDoc } from './BorrowerDataTerm.model';
import { IBorrowerDataBootCollateralDoc } from './BorrowerDataBootCollateral.model';
import { MODEL_NAMES } from './_models';

export interface IBorrowerSettings {
  borrower: mongoose.Types.ObjectId;
  queries: { [group: string]: { [queryName: string]: { isCalculateOnUpload: boolean, params: object, extraParams?: object } } };
  dataTypes: { [group: string]: string[] };
  dataAvailability: {
    [key in 'receivables' | 'inventories']: boolean;
  }
  data: {
    [key in 'options' | 'receivables' | 'inventories' | 'contacts' | 'guarantees' | 'locations' | 'banks' | 'insurance' | 'terms' | 'bootCollaterals']: mongoose.Types.ObjectId[];
  },
}

export interface IBorrowerSettingsDoc extends IBorrowerSettings, Document {
}

export interface IBorrowerSettingsDocPopulated extends Omit<IBorrowerSettings, 'data'> {
  data: {
    options: IBorrowerDataDocWithName[];
    receivables: IBorrowerDataReceivableDoc[];
    inventories: IBorrowerDataInventoryDoc[];
    terms: IBorrowerDataTermDoc[];
    bootCollaterals: IBorrowerDataBootCollateralDoc[];
    contacts: IBorrowerDataContactDoc[];
    guarantees: IBorrowerDataGuaranteeDoc[];
    locations: IBorrowerDataLocationDoc[];
    banks: IBorrowerDataBankDoc[];
    insurance: IBorrowerDataInsuranceDoc[];
  };
}

export const dataAvailabilitySchema = new mongoose.Schema(
  {
    receivables: {
      type: Boolean,
      default: false,
    },
    inventories: {
      type: Boolean,
      default: false,
    },
  },
  { _id: false, timestamps: false, versionKey: false });

export const dataSchema = new mongoose.Schema(
  {
    options: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerData,
    }],
    receivables: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataReceivables,
    }],
    inventories: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataInventories,
    }],
    terms: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataTerms,
    }],
    bootCollaterals: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataBootCollaterals,
    }],
    contacts: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataContacts,
    }],
    guarantees: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataGuarantees,
    }],
    locations: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataLocations,
    }],
    banks: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataBanks,
    }],
    insurance: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowerDataInsurances,
    }],
  },
  { _id: false, timestamps: false, versionKey: false });

export const BorrowerSettingsSchema = new mongoose.Schema(
  {
    borrower: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.borrowers,
      required: true,
    },
    queries: {
      required: false,
      type: Object,
      default: {},
    },
    dataTypes: {
      required: false,
      type: Object,
      default: {},
    },
    dataAvailability: dataAvailabilitySchema,
    data: dataSchema,
    __v: { type: Number, select: false },
  },
  { timestamps: true },
);

export const BorrowerSettingsModel: mongoose.Model<IBorrowerSettingsDoc> = mongoose.model<IBorrowerSettingsDoc>(MODEL_NAMES.borrowerSettings, BorrowerSettingsSchema);
