import mongoose, { Document, Model } from 'mongoose';
import Joi from 'joi';

import { MODEL_NAMES } from './_models';

import { ExternalProspectStageTwoTables, ProspectInfoStageTwo } from './ProspectInfoStageTwo.model';
import { ExternalProspectStageOneTables, ProspectInfoStageOne } from './ProspectInfoStageOne.model';
import { getUUID, TDictionary } from '../helpers/main.helper';
import { CRMProspectInfoNoteSchema, ICRMProspectInfoNote } from './ProspectInfoNote.model';
import { IProspectFile } from './ProspectFile.model';

const textFieldMaxLength = 600;

export const prospectFieldsDictionary: TDictionary = {
  name: 'Name',
  industry: 'Industry',
  status: 'Status',
  probability: 'Probability',
  revolverAmount: 'Revolver Amount',
  termAmount: 'Term Amount',
  keyDates: {
    lastContact: 'Last Contact',
    receivedDate: 'Received Date',
    LOISubmitted: 'LOI Submitted',
    DDStarted: 'DD Started',
    expectedFunding: 'Expected Funding',
    dropDate: 'Drop Date',
  },
  priority: 'Priority',
  declineReason: 'Decline Reason',
  sourceId: 'Source',
  collaterals: {
    equipment: 'Equipment',
    inventory: 'Inventory',
    receivables: 'Receivables',
    other: 'Other',
  },
  closingPoints: 'Closing Points',
  comments: 'Comments',
};

export const sharepointFoldersDictionary = {
  confidential: 'Confidential - Personal Information',
  confidentialDeclined: 'Declined',

  // TOP
  legal: 'Legal',
  portfolio: 'Portfolio',
  underwriting: 'Underwriting',

  // > Legal
  drafts: 'Drafts',
  finalDocuments: 'Final Documents',

  // > Portfolio
  APReports: '01. AP Reports',
  ARReports: '02. AR Reports',
  borrowingBaseCertificatesAndBackup: '03. Borrowing Base Certificates and Backup',
  financials: '04. Financials',
  inventory: '05. Inventory',
  machineryEquipment: '06. Machinery & Equipment',
  taxes: '07. Taxes',
  insurance: '08. Insurance',
  fieldExams: '09. Field Exams',
  payments: '10. Payments',
  interestStatements: '11. Interest Statements',
  leasesRealEstate: '12. Leases & Real Estate',
  agreementsContracts: '13. Agreements & Contracts',
  liensLitigation: '14. Liens & Litigation',
  verifications: '15. Verifications',
  onlineBankingInstructions: '16. Online Banking Instructions',
  compliance: '17. Compliance',
  portfolio_other: '18. Other',

  // > Underwriting
  dueDiligence: '01. Due Diligence',
  loi: '02. LOI',
  loanMemoApprovals: '03. Loan Memo & Approvals',

  // > Underwriting > 02. LOI
  loiTemplates: 'zz Templates',

  // > Underwriting > 03. Loan Memo & Approvals
  loanMemo: '01. Loan Memo',
  dataTablesWorkings: '02. Data, Tables & Workings',
  approvalEmails: '03. Approval Emails',
  templatesSamples: 'zz Templates and Samples',

  // > Underwriting > 01. Due Diligence
  corporateDocuments: '01. Corporate Documents',
  // > Underwriting > 01. Due Diligence > 01. Corporate Documents
  organizationDocumentsGoodStandings: 'a. Organization Documents and Good Standings',
  disclosureSchedule: 'b. Disclosure Schedule',
  corporateDocuments_insurance: 'c. Insurance',
  ownership: 'd. Ownership',
  officersManagersStaff: 'e. Officers, Managers, Staff',

  // > Underwriting > 01. Due Diligence
  lienLitigationSearchesTaxes: '02. Lien & Litigation Searches and Taxes',
  // > Underwriting > 01. Due Diligence > 02. Lien & Litigation Searches and Taxes
  lienLitigationSearch: 'a. Lien & Litigation Search',
  disclosedLitigations: 'b. Disclosed Litigations',
  payrollTaxStatementsProofOfPayment: 'c. Payroll Tax Statements & Proof of Payment',
  incomeTaxReturns: 'd. Income Tax Returns',
  personalPropertyTaxStatementsProofOfPayment: 'e. Personal Property Tax Statements and Proof of Payment',

  // > Underwriting > 01. Due Diligence
  KYC: '03. KYC',

  // > Underwriting > 01. Due Diligence
  collateral: '04. Collateral',
  // > Underwriting > 01. Due Diligence > 04. Collateral
  collateral_inventory: 'a. Inventory',
  receivables: 'b. Receivables',
  equipment: 'c. Equipment',
  fieldExamAppraisals: 'd. Field Exam & Appraisals',
  borrowingBases: 'e. Borrowing Bases',

  // > Underwriting > 01. Due Diligence
  financialsBankStatements: '05. Financials and Bank Statements',
  // > Underwriting > 01. Due Diligence > 05. Financials and Bank Statements
  historicalFinancials: 'a. Historical Financials',
  projections: 'b. Projections',
  bankStatements: 'c. Bank Statements',
  accountsPayables: 'd. Accounts Payables',
  currentDebt: 'e. Current Debt',

  // > Underwriting > 01. Due Diligence
  majorContracts: '06. Major Contracts',
  // > Underwriting > 01. Due Diligence > 06. Major Contracts
  leases: 'a. Leases',
  it: 'b. IT',
  majorContracts_other: 'c. Other',

  // > Underwriting > 01. Due Diligence
  intellectualProperty: '07. Intellectual Property',

  // > Underwriting > 01. Due Diligence
  fieldExamRequests: '08. Field Exam Requests',

  // > Underwriting > 01. Due Diligence
  customerVendorLists: '09. Customer & Vendor Lists',

  // > Underwriting > 01. Due Diligence
  other: '10. Other',

  // > Underwriting > 01. Due Diligence
  standardEmailAttachments: 'zz Standard Email Attachments',
  underwriting_templates: 'zz Templates',
} as const;

export type TSharepointFolderKey = keyof typeof sharepointFoldersDictionary;
export type TSharepointFolderValue = typeof sharepointFoldersDictionary[TSharepointFolderKey];
export type TSharepointFolder = typeof sharepointFoldersDictionary[TSharepointFolderKey];

export enum EProspectPriority {
  LOW = 'LOW',
  MEDIUM = 'MEDIUM',
  HIGH = 'HIGH',
}

export enum EProspectStatus {
  PROSPECT = 'PROSPECT',
  TERM_SHEET = 'TERM_SHEET',
  DUE_DILIGENCE = 'DUE_DILIGENCE',
  PHASE_2 = 'PHASE_2',
  LOAN_DOCUMENTS = 'LOAN_DOCUMENTS',
  FUNDED = 'FUNDED',
}

export enum EProspectStatusDict {
  PROSPECT = 'Prospect',
  TERM_SHEET = 'Term Sheet',
  DUE_DILIGENCE = 'Due Diligence',
  PHASE_2 = 'Phase II',
  LOAN_DOCUMENTS = 'Loan Documents',
  FUNDED = 'Funded',
}

export enum EProspectDeclineReason {
  NOT_DECLINED = 'NOT_DECLINED',
  DO_NOT_LIKE_COLLATERAL = 'DO_NOT_LIKE_COLLATERAL',
  INSUFFICIENT_COLLATERAL = 'INSUFFICIENT_COLLATERAL',
  LOST_TO_COMPETITOR = 'LOST_TO_COMPETITOR',
  DOES_NOT_FIT_LENDING_CRITERIA = 'DOES_NOT_FIT_LENDING_CRITERIA',
  DATA_QUALITY = 'DATA_QUALITY',
  DID_NOT_HEAR_BACK = 'DID_NOT_HEAR_BACK',
  NOT_ENOUGH_CAPITAL_TO_FUND = 'NOT_ENOUGH_CAPITAL_TO_FUND',
}

interface IProspectProduct {
  commitment: number;
  expected: number;
  maturity: number;
}

export interface IProspectBase {
  isDeclined: boolean;
  name: string;
  industryId: mongoose.Types.ObjectId;
  status: EProspectStatus;
  revolver: IProspectProduct;
  term: IProspectProduct;
}

export interface IProspectInfoRow {
  _id: string;
  name: string;
  value: string;
  extraValue?: string;
}

export interface IProspectInfoStageOne {
  companyLegalName: string;
  companyLegalAddress: string;
  companyCorrespondenceAddress: string;
  DBANames: string;
  websiteAddress: string;
  businessDescription: string;
  [ExternalProspectStageOneTables.litigation]: unknown[],
  [ExternalProspectStageOneTables.detailsOfCurrentDebt]: unknown[],
}

export interface IProspectInfoStageTwo {
  [ExternalProspectStageTwoTables.listOfShareholders]: unknown[];
  [ExternalProspectStageTwoTables.listOfOfficers]: unknown[];
  [ExternalProspectStageTwoTables.listOfManagers]: unknown[];
  [ExternalProspectStageTwoTables.addressesOfOffices]: unknown[];
  [ExternalProspectStageTwoTables.addressesOfWarehouses]: unknown[];
  [ExternalProspectStageTwoTables.topCustomers]: unknown[];
  [ExternalProspectStageTwoTables.itSystems]: unknown[],
  [ExternalProspectStageTwoTables.insuranceBrokers]: unknown[],
  [ExternalProspectStageTwoTables.insurancePolicies]: unknown[],
  [ExternalProspectStageTwoTables.financialInformation]: unknown[],
  [ExternalProspectStageTwoTables.accountsReceivables]: unknown[],
  [ExternalProspectStageTwoTables.accountsReceivablesLists]: unknown[],
  [ExternalProspectStageTwoTables.accountsReceivablesExtra]: unknown[],
  [ExternalProspectStageTwoTables.accountsReceivablesContacts]: unknown[],
  [ExternalProspectStageTwoTables.inventoryInformationFiles]: unknown[],
  [ExternalProspectStageTwoTables.inventoryInformationDetails]: unknown[],
  [ExternalProspectStageTwoTables.inventoryInformation]: unknown[],
  [ExternalProspectStageTwoTables.equipment]: unknown[],
}

export interface IProspectExternalInfo {
  stageOne: IProspectInfoStageOne;
  stageTwo: IProspectInfoStageTwo;
  notes: ICRMProspectInfoNote[];
}

export interface IProspectExternalNew {
  isLocked: boolean;
  lastSentDate: Date;
  info: IProspectExternalInfo;
}

export enum EProspectFileGroups {
  borrowingBase = 'borrowingBase',
  corporateDocuments = 'corporateDocuments',
  ownershipStructure = 'ownershipStructure',
  organizationStructure = 'organizationStructure',
  financialsBankInformation = 'financialsBankInformation',
  financialsBankInformation_historicalFinancials = 'financialsBankInformation_historicalFinancials',
  financialsBankInformation_projections = 'financialsBankInformation_projections',
  financialsBankInformation_bankStatements = 'financialsBankInformation_bankStatements',
  historicalFinancials = 'historicalFinancials',
  projections = 'projections',
  accountsPayables = 'accountsPayables',
  collateralSales = 'collateralSales',
  receivables = 'receivables',
  taxes = 'taxes',
  taxesIncome = 'taxesIncome',
  taxesProperty = 'taxesProperty',
  taxesPayroll = 'taxesPayroll',
  majorContracts = 'majorContracts',
  payrollRegister = 'payrollRegister',
  litigationSummary = 'litigationSummary',
  litigation = 'litigation',
  itSystems = 'itSystems',
  trademark = 'trademark',
  websites = 'websites',
  perfectionCertificate = 'perfectionCertificate',
  other = 'other',
  fieldAppraisal = 'fieldAppraisal',

  confidential = 'confidential',
  confidentialPersonalFinancial = 'confidentialPersonalFinancial',
  confidentialDriverLicenses = 'confidentialDriverLicenses',
  confidentialReferences = 'confidentialReferences',
}

export const prospectFileGroups: string[] = [
  EProspectFileGroups.borrowingBase,
  EProspectFileGroups.corporateDocuments,
  EProspectFileGroups.financialsBankInformation,
  EProspectFileGroups.financialsBankInformation_historicalFinancials,
  EProspectFileGroups.financialsBankInformation_bankStatements,
  EProspectFileGroups.financialsBankInformation_projections,
  EProspectFileGroups.collateralSales,
  EProspectFileGroups.taxes,
  EProspectFileGroups.taxesIncome,
  EProspectFileGroups.taxesProperty,
  EProspectFileGroups.taxesPayroll,
  EProspectFileGroups.majorContracts,
  EProspectFileGroups.payrollRegister,
  EProspectFileGroups.litigationSummary,

  EProspectFileGroups.litigation,
  EProspectFileGroups.itSystems,
  EProspectFileGroups.trademark,
  EProspectFileGroups.websites,
  EProspectFileGroups.perfectionCertificate,
  EProspectFileGroups.other,

  EProspectFileGroups.confidential,
  EProspectFileGroups.confidentialPersonalFinancial,
  EProspectFileGroups.confidentialDriverLicenses,
  EProspectFileGroups.confidentialReferences,
  EProspectFileGroups.fieldAppraisal,

  ExternalProspectStageOneTables.detailsOfCurrentDebt,
  ExternalProspectStageOneTables.litigation,
  ExternalProspectStageTwoTables.financialInformation,
  ExternalProspectStageTwoTables.accountsReceivables,
  ExternalProspectStageTwoTables.inventoryInformationFiles,
  ExternalProspectStageTwoTables.equipment,
  ExternalProspectStageTwoTables.addressesOfOffices,
  ExternalProspectStageTwoTables.addressesOfWarehouses,
  ExternalProspectStageTwoTables.listOfManagers,
  ExternalProspectStageTwoTables.listOfShareholders,
  ExternalProspectStageTwoTables.listOfOfficers,
  ExternalProspectStageTwoTables.itSystems,
  ExternalProspectStageTwoTables.insuranceBrokers,
  ExternalProspectStageTwoTables.insurancePolicies,
  ExternalProspectStageTwoTables.accountsReceivablesExtra,
  ExternalProspectStageTwoTables.inventoryInformation,
];

export const prospectFileGroupsMap = {
  [EProspectFileGroups.borrowingBase]: 'Borrowing Base',
  [EProspectFileGroups.corporateDocuments]: 'Collateral & Sales',
  [EProspectFileGroups.financialsBankInformation]: 'Financials & Bank Information',
  [EProspectFileGroups.collateralSales]: 'Collateral & Sales',
  [EProspectFileGroups.taxes]: 'Taxes',
  [EProspectFileGroups.taxesIncome]: 'Upload Payroll Tax Statements & Proof of Payment',
  [EProspectFileGroups.taxesProperty]: 'Upload Income Tax Returns',
  [EProspectFileGroups.taxesPayroll]: 'Upload Personal Property Tax Statements & Proof of Payment',
  [EProspectFileGroups.majorContracts]: 'Major Contracts',
  [EProspectFileGroups.payrollRegister]: 'Payroll Register',
  [EProspectFileGroups.litigationSummary]: 'Litigation Summary',
  [EProspectFileGroups.fieldAppraisal]: 'Field Appraisal or Audit Requests',

  [EProspectFileGroups.confidential]: 'Confidential',
  [EProspectFileGroups.confidentialPersonalFinancial]: 'Personal Financial Statements',
  [EProspectFileGroups.confidentialDriverLicenses]: 'Driver Licenses',
  [EProspectFileGroups.confidentialReferences]: 'References',

  [ExternalProspectStageOneTables.detailsOfCurrentDebt]: 'Details Of CurrentDebt',
  [ExternalProspectStageOneTables.litigation]: 'Summary of Litigation',
  [ExternalProspectStageTwoTables.financialInformation]: 'Financial Information',
  [ExternalProspectStageTwoTables.accountsReceivables]: 'Accounts Receivables',
  [ExternalProspectStageTwoTables.inventoryInformationFiles]: 'Inventory Information Files',
  [ExternalProspectStageTwoTables.addressesOfOffices]: 'Addresses Of Offices',
  [ExternalProspectStageTwoTables.addressesOfWarehouses]: 'Addresses Of Warehouses',
  [ExternalProspectStageTwoTables.equipment]: 'Equipment',
  [ExternalProspectStageTwoTables.listOfManagers]: 'List Of Managers',
  [ExternalProspectStageTwoTables.listOfShareholders]: 'List Of Shareholders',
  [ExternalProspectStageTwoTables.listOfOfficers]: 'List Of Officers',
  [ExternalProspectStageTwoTables.itSystems]: 'IT Systems',
  [ExternalProspectStageTwoTables.insuranceBrokers]: 'Insurance Brokers',
  [ExternalProspectStageTwoTables.insurancePolicies]: 'Insurance Brokers',
  [ExternalProspectStageTwoTables.accountsReceivablesExtra]: 'Accounts Receivables Extra',
  [ExternalProspectStageTwoTables.inventoryInformation]: 'Inventory Information',
};

export const NO_ROW_ID = '__no_row__';

export const initialFileGroups = () => prospectFileGroups.reduce((acc, g) => {
  return { ...acc, [g]: { [NO_ROW_ID]: [] } };
}, {});

export const externalProspectInitialInfo = (): IProspectExternalNew => ({
  isLocked: false,
  lastSentDate: null,
  info: {
    stageOne: {
      companyLegalName: '',
      companyLegalAddress: '',
      companyCorrespondenceAddress: '',
      DBANames: '',
      websiteAddress: '',
      businessDescription: '',
      [ExternalProspectStageOneTables.litigation]: [
        {
          _id: getUUID(),
          title: 'Describe any previous, current or threatened litigation. If no litigation, please state “No previous, current or threatened litigation".',
          comment: '',
        },
      ],
      [ExternalProspectStageOneTables.detailsOfCurrentDebt]: [],
    },
    stageTwo: {
      [ExternalProspectStageTwoTables.listOfShareholders]: [],
      [ExternalProspectStageTwoTables.listOfOfficers]: [],
      [ExternalProspectStageTwoTables.listOfManagers]: [],
      [ExternalProspectStageTwoTables.addressesOfOffices]: [],
      [ExternalProspectStageTwoTables.addressesOfWarehouses]: [],
      [ExternalProspectStageTwoTables.topCustomers]: [
        { _id: getUUID(), name: '', value: '' },
        { _id: getUUID(), name: '', value: '' },
        { _id: getUUID(), name: '', value: '' },
        { _id: getUUID(), name: '', value: '' },
        { _id: getUUID(), name: '', value: '' },
      ],
      [ExternalProspectStageTwoTables.itSystems]: [],
      [ExternalProspectStageTwoTables.insuranceBrokers]: [],
      [ExternalProspectStageTwoTables.insurancePolicies]: [],
      [ExternalProspectStageTwoTables.financialInformation]: [
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.financialsBankInformation_historicalFinancials,
          title: 'Prior 2 years and YTD Income Statement & Balance Sheet in Excel Format',
        },
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.financialsBankInformation_projections,
          title: 'Currently Monthly Projections',
        },
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.financialsBankInformation_bankStatements,
          title: 'Last 3 Month Bank Statements',
        },
      ],
      [ExternalProspectStageTwoTables.accountsReceivables]: [
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.accountsPayables,
          title: 'Excel Format: Current and past 12 months A/P aging report by invoice date',
        },
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.receivables,
          title: 'Excel Format: Current and past 12 months A/R aging report by invoice date',
        },
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.receivables,
          title: 'Excel Format: A/R dilution (write-offs) for the trailing 3 months and 12 months',
        },
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.receivables,
          title: 'Excel Format: Outstanding / held checks list',
        },
        {
          _id: getUUID(),
          _sharepointFolder: EProspectFileGroups.receivables,
          title: 'Excel Format: Average A/R and A/P turnover in days for the trailing 3 months and 12 months',
        },
      ],
      [ExternalProspectStageTwoTables.accountsReceivablesLists]: [
        {
          _id: getUUID(),
          title: 'Excel Format: Customer list with name, contact name, phone, email and address',
        },
        {
          _id: getUUID(),
          title: 'Excel Format: Vendor list with name, contact name, phone, email and address',
        },
      ],
      [ExternalProspectStageTwoTables.accountsReceivablesExtra]: [
        {
          _id: getUUID(),
          title: 'Describe any problems collecting AR in the last 2 years.',
          comment: '',
        },
        {
          _id: getUUID(),
          title: 'Detail any relationships where AR and AP are to the same person (i.e. a supplier is also a customer)',
          comment: '',
        },
      ],
      [ExternalProspectStageTwoTables.accountsReceivablesContacts]: [],
      [ExternalProspectStageTwoTables.inventoryInformation]: [],
      [ExternalProspectStageTwoTables.inventoryInformationDetails]: [
        {
          _id: getUUID(),
          title: 'How often is a physical inventory conducted?',
        },
        {
          _id: getUUID(),
          title: 'What is the historical physical inventory discrepancy for the past 2 years?',
        },
      ],
      [ExternalProspectStageTwoTables.inventoryInformationFiles]: [
        {
          _id: getUUID(),
          title: 'Excel Format: Current inventory report by SKU. Include breakdown by Raw, WIP and FG',
        },
        {
          _id: getUUID(),
          title: 'Excel Format: If possible either (a) inventory turnover report by SKU or (b) sales by SKU by month for trailing 12 months',
        },
        { _id: getUUID(), title: 'Excel Format: Old and/or obsolete / damaged inventory report' },
      ],
      [ExternalProspectStageTwoTables.equipment]: [
        { _id: getUUID(), title: 'Current schedule of fixed assets and depreciation schedule' },
        {
          _id: getUUID(),
          title: 'Depreciation schedule for such assets, specifically for the equipment for this proposed financing',
        },
        { _id: getUUID(), title: 'Copies of invoices for equipment purchases over $50,000' },
        { _id: getUUID(), title: 'Copies of any calibration certificates and schedule of due dates' },
        { _id: getUUID(), title: 'Copies of titles for titled equipment' },
        { _id: getUUID(), title: 'Copy of any prior appraisals' },
      ],
    },
    notes: [],
  },
});

export type TProspectFiles = {
  [K in typeof prospectFileGroups[number]]: { [rowId: string]: IProspectFile[] };
};

export type TProspectAuditorFiles = Map<string, IProspectFile[]>;

export interface IProspectContact {
  name: string;
  email: string;
  phone: string;
  comment: string;
  companyName: string;
}

export interface IProspect extends IProspectBase, IProspectExternalNew {
  isLocked: boolean;
  probability: number;
  businessDescription: string;
  comments: string;
  collateralDescription: string;
  declineReason: EProspectDeclineReason;
  priority: EProspectPriority;
  sourceId: mongoose.Types.ObjectId;
  collaterals: {
    equipment: boolean;
    inventory: boolean;
    receivables: boolean;
    other: boolean;
  };
  keyDates: {
    lastContact: Date,
    receivedDate: Date,
    LOISubmitted: Date,
    DDStarted: Date,
    expectedFunding: Date,
    dropDate: Date,
  },
  closingPoints: number;
  expectedLoanYield: number;
  depositRequested: number;
  state: string;
  contacts: IProspectContact[];
  underwriterIds: mongoose.Types.ObjectId[];
  auditorIds: mongoose.Types.ObjectId[];
  appraiserIds: mongoose.Types.ObjectId[];
}

export interface IProspectBaseWithId extends IProspectBase {
  _id: string;
}

export interface IProspectWithId extends IProspect {
  _id: string;
}

export type IProspectExternal = Pick<IProspectWithId, 'info' | 'isLocked' | 'status' | '_id'> & {
  auditorFiles: IProspectFile[];
  files: IProspectFile[];
}

export type IProspectExternalAuditors = Pick<IProspectWithId, 'info' | 'isLocked'> & {
  files: IProspectFile[];
  auditorFiles: IProspectFile[];
  auditorSharedFiles: IProspectFile[];
}

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

export interface IProspectLean extends IProspect {
  _id: mongoose.Types.ObjectId;
  createdAt: Date;
  updatedAt: Date;
}

export interface IProspectPlain extends IProspect {
  _id: string;
  createdAt: Date;
  updatedAt: Date;
}

export const baseFields = ['_id', 'industry', 'status', 'revolverAmount', 'termAmount', 'keyDates'];

const ProspectInfoRowValidationSchema = Joi.object({
  _id: Joi.string().allow(NO_ROW_ID),
  name: Joi.string().allow('', null),
  value: Joi.string().allow('', null),
  extraValue: Joi.string().allow('', null),
});

export const ProspectInfoExternalValidationSchema = Joi.object({
  companyLegalName: Joi.string().allow('', null),
  companyLegalAddress: Joi.string().allow('', null),
  companyCorrespondenceAddress: Joi.string().allow('', null),
  DBANames: Joi.string().allow('', null),
  websiteAddress: Joi.string().allow('', null),
  businessDescription: Joi.string().allow('', null),
  listOfShareholders: Joi.array().items(ProspectInfoRowValidationSchema),
  listOfOfficers: Joi.array().items(ProspectInfoRowValidationSchema),
  listOfManagers: Joi.array().items(ProspectInfoRowValidationSchema),
  addressesOfOffices: Joi.array().items(ProspectInfoRowValidationSchema),
  addressesOfWarehouses: Joi.array().items(ProspectInfoRowValidationSchema),
  top5Customers: Joi.array().items(ProspectInfoRowValidationSchema),
});

export const ProspectInfoValidationSchema = Joi.object({
  isLocked: Joi.boolean().allow(null),
  lastSentDate: Joi.date().allow(null),
});

export const ProspectValidationSchema = Joi.object({
  _id: Joi.string(),
  isDeclined: Joi.boolean().allow(null),
  name: Joi.string().required(),
  industryId: Joi.string().required(),
  status: Joi.string().valid(...Object.values(EProspectStatus)).required(),
  probability: Joi.number().required(),
  depositRequested: Joi.number().required(),
  revolver: Joi.object({
    commitment: Joi.number(),
    expected: Joi.number(),
    maturity: Joi.number().integer(),
  }).or('commitment', 'expected', 'maturity'),
  term: Joi.object({
    commitment: Joi.number(),
    expected: Joi.number(),
    maturity: Joi.number().integer(),
  }).or('commitment', 'expected', 'maturity'),
  collaterals: Joi.object({
    equipment: Joi.boolean().required(),
    inventory: Joi.boolean().required(),
    receivables: Joi.boolean().required(),
    other: Joi.boolean().required(),
  }),
  keyDates: Joi.object({
    lastContact: Joi.date(),
    receivedDate: Joi.date(),
    LOISubmitted: Joi.date().allow(null),
    DDStarted: Joi.date().allow(null),
    expectedFunding: Joi.date().allow(null),
    dropDate: Joi.date().allow(null),
  }),
  priority: Joi.string().valid(...Object.values(EProspectPriority)).required(),
  businessDescription: Joi.string().max(textFieldMaxLength).allow(''),
  comments: Joi.string().max(textFieldMaxLength).allow(''),
  collateralDescription: Joi.string().max(textFieldMaxLength).allow(''),
  declineReason: Joi.string().valid(...Object.values(EProspectDeclineReason)),
  sourceId: Joi.string().required(),
  // closingPoints: Joi.number().required().allow(null, 0).default(0),
  // expectedLoanYield: Joi.number().required().allow(null, 0).default(0),
  state: Joi.string().required(),
  contacts: Joi.array().items(Joi.object({
    name: Joi.string().required().allow('', null).default(''),
    email: Joi.string().required().allow('', null).default(''),
    phone: Joi.string().required().allow('', null).default(''),
    comment: Joi.string().required().allow('', null).default(''),
    companyName: Joi.string().required().allow('', null).default(''),
  })),
  underwriterIds: Joi.array().items(Joi.string()),
  auditorIds: Joi.array().items(Joi.string()),
  appraiserIds: Joi.array().items(Joi.string()),
  acceptedFiles: Joi.array().items(Joi.string()).allow(null),
}).concat(ProspectInfoValidationSchema);

export type ProspectModel = Model<IProspectDoc>;

const contactSchema = new mongoose.Schema({
  name: {
    type: String,
    required: false,
    default: '',
  },
  email: {
    type: String,
    required: false,
    default: '',
  },
  phone: {
    type: String,
    required: false,
    default: '',
  },
  comment: {
    type: String,
    required: false,
    default: '',
  },
  companyName: {
    type: String,
    required: false,
    default: '',
  },
}, { _id: false });

const ProspectInfoSchema = {
  isLocked: {
    type: Boolean,
  },
  lastSentDate: {
    type: Date,
  },
  info: {
    stageOne: ProspectInfoStageOne,
    stageTwo: ProspectInfoStageTwo,
    notes: { type: [CRMProspectInfoNoteSchema], default: [] },
  },
};

export const ProspectSchema = new mongoose.Schema<IProspect, ProspectModel>(
  {
    isLocked: {
      type: Boolean,
    },
    isDeclined: {
      type: Boolean,
    },
    name: {
      type: String,
      trim: true,
    },
    industryId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.CRMProspectIndustries,
    },
    status: {
      type: String,
      enum: Object.values(EProspectStatus),
    },
    probability: {
      type: Number,
    },
    revolver: {
      commitment: {
        type: Number,
      },
      expected: {
        type: Number,
      },
      maturity: {
        type: Number,
      },
    },
    term: {
      commitment: {
        type: Number,
      },
      expected: {
        type: Number,
      },
      maturity: {
        type: Number,
      },
    },
    priority: {
      type: String,
      enum: Object.values(EProspectPriority),
    },
    declineReason: {
      type: String,
      enum: Object.values(EProspectDeclineReason),
    },
    businessDescription: {
      type: String,
    },
    comments: {
      type: String,
    },
    collateralDescription: {
      type: String,
    },
    sourceId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.CRMProspectSources,
    },
    collaterals: {
      equipment: {
        type: Boolean,
      },
      inventory: {
        type: Boolean,
      },
      receivables: {
        type: Boolean,
      },
      other: {
        type: Boolean,
      },
    },
    closingPoints: {
      type: Number,
    },
    expectedLoanYield: {
      type: Number,
    },
    depositRequested: {
      type: Number,
    },
    keyDates: {
      lastContact: {
        type: Date,
      },
      receivedDate: {
        type: Date,
      },
      LOISubmitted: {
        type: Date,
      },
      DDStarted: {
        type: Date,
      },
      expectedFunding: {
        type: Date,
      },
      dropDate: {
        type: Date,
      },
    },
    state: {
      type: String,
    },
    contacts: [contactSchema],
    ...ProspectInfoSchema,
    underwriterIds: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.underwriters,
    }],
    auditorIds: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.auditors,
    }],
    appraiserIds: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: MODEL_NAMES.appraiser,
    }],
  },
  {
    timestamps: { createdAt: true, updatedAt: true },
    versionKey: false,
  },
);

export const Prospect = mongoose.model<IProspect, ProspectModel>(MODEL_NAMES.CRMProspects, ProspectSchema);
