/**
 * Cap Table Model
 *
 * Shareholder tracking, ownership percentages, dilution analysis, and vesting schedules.
 */

import mongoose, { Schema, Document, models, Model } from 'mongoose';

// ============================================
// TYPES
// ============================================

export type ShareholderType = 'founder' | 'employee' | 'investor' | 'option-pool' | 'convertible' | 'other';
export type ShareClass = 'common' | 'preferred-series-a' | 'preferred-series-b' | 'preferred-series-c' | 'convertible-note' | 'safe';
export type VestingType = '4-year-1-year-cliff' | '3-year-1-year-cliff' | 'immediate';

export interface IVestingSchedule {
  totalShares: number;
  vested: number;
  unvested: number;
  cliffDate?: string;
  vestingEndDate?: string;
  vestingType?: VestingType;
}

export interface IOptionDetails {
  granted: number;
  exercised: number;
  remaining: number;
  strikePrice?: number;
  expiryDate?: string;
}

export interface IShareholder {
  id: string;
  name: string;
  type: ShareholderType;
  email?: string;
  shares: number;
  shareClass: ShareClass;
  percentage: number;
  vestingSchedule?: IVestingSchedule;
  options?: IOptionDetails;
  notes?: string;
  investmentDate?: string;
}

export interface IDilutionScenario {
  id: string;
  name: string;
  roundType: string;
  amount: number;
  preMoneyValuation: number;
  newSharesIssued: number;
  resultingOwnership: Record<string, number>;
  createdAt: Date;
}

export interface ICapTableHistory {
  date: Date;
  event: string;
  changes: string;
  previousState: IShareholder[];
}

export interface ICapTableDocument {
  id: string;
  name: string;
  type: 'cap-table' | '409a-valuation' | 'board-consent' | 'other';
  url: string;
  uploadedAt: Date;
}

export interface IOptionPool {
  totalShares: number;
  allocated: number;
  available: number;
  approvedBy?: string;
  approvedAt?: Date;
}

export interface ICapTable extends Document {
  companyId: string;
  shareholders: IShareholder[];
  totalShares: number;
  totalFullyDiluted: number;
  optionPool?: IOptionPool;
  dilutionScenarios?: IDilutionScenario[];
  history?: ICapTableHistory[];
  documents?: ICapTableDocument[];
  lastUpdated: Date;
  createdBy: string;
  createdAt: Date;
  updatedAt: Date;
}

// ============================================
// SCHEMA
// ============================================

const VestingScheduleSchema = new Schema<IVestingSchedule>(
  {
    totalShares: { type: Number, default: 0 },
    vested: { type: Number, default: 0 },
    unvested: { type: Number, default: 0 },
    cliffDate: { type: String },
    vestingEndDate: { type: String },
    vestingType: {
      type: String,
      enum: ['4-year-1-year-cliff', '3-year-1-year-cliff', 'immediate'],
    },
  },
  { _id: false }
);

const OptionDetailsSchema = new Schema<IOptionDetails>(
  {
    granted: { type: Number, default: 0 },
    exercised: { type: Number, default: 0 },
    remaining: { type: Number, default: 0 },
    strikePrice: { type: Number },
    expiryDate: { type: String },
  },
  { _id: false }
);

const ShareholderSchema = new Schema<IShareholder>(
  {
    id: { type: String, required: true },
    name: { type: String, required: true },
    type: {
      type: String,
      enum: ['founder', 'employee', 'investor', 'option-pool', 'convertible', 'other'],
      required: true,
    },
    email: { type: String },
    shares: { type: Number, required: true, min: 0 },
    shareClass: {
      type: String,
      enum: ['common', 'preferred-series-a', 'preferred-series-b', 'preferred-series-c', 'convertible-note', 'safe'],
      default: 'common',
    },
    percentage: { type: Number, default: 0, min: 0, max: 100 },
    vestingSchedule: VestingScheduleSchema,
    options: OptionDetailsSchema,
    notes: { type: String },
    investmentDate: { type: String },
  },
  { _id: false }
);

const DilutionScenarioSchema = new Schema<IDilutionScenario>(
  {
    id: { type: String, required: true },
    name: { type: String, required: true },
    roundType: { type: String, required: true },
    amount: { type: Number, required: true },
    preMoneyValuation: { type: Number, required: true },
    newSharesIssued: { type: Number, required: true },
    resultingOwnership: { type: Schema.Types.Mixed, default: {} },
    createdAt: { type: Date, default: Date.now },
  },
  { _id: false }
);

const CapTableHistorySchema = new Schema<ICapTableHistory>(
  {
    date: { type: Date, required: true },
    event: { type: String, required: true },
    changes: { type: String, required: true },
    previousState: [ShareholderSchema],
  },
  { _id: false }
);

const CapTableDocumentSchema = new Schema<ICapTableDocument>(
  {
    id: { type: String, required: true },
    name: { type: String, required: true },
    type: {
      type: String,
      enum: ['cap-table', '409a-valuation', 'board-consent', 'other'],
      required: true,
    },
    url: { type: String, required: true },
    uploadedAt: { type: Date, default: Date.now },
  },
  { _id: false }
);

const OptionPoolSchema = new Schema<IOptionPool>(
  {
    totalShares: { type: Number, default: 0 },
    allocated: { type: Number, default: 0 },
    available: { type: Number, default: 0 },
    approvedBy: { type: String },
    approvedAt: { type: Date },
  },
  { _id: false }
);

const CapTableSchema = new Schema<ICapTable>(
  {
    companyId: { type: String, required: true, unique: true, index: true },
    shareholders: [ShareholderSchema],
    totalShares: { type: Number, default: 0, min: 0 },
    totalFullyDiluted: { type: Number, default: 0, min: 0 },
    optionPool: OptionPoolSchema,
    dilutionScenarios: [DilutionScenarioSchema],
    history: [CapTableHistorySchema],
    documents: [CapTableDocumentSchema],
    lastUpdated: { type: Date, default: Date.now },
    createdBy: { type: String, required: true },
  },
  { timestamps: true }
);

// Pre-save hook to recalculate percentages
CapTableSchema.pre('save', function (next) {
  if (this.shareholders && Array.isArray(this.shareholders) && this.totalShares > 0) {
    this.shareholders = this.shareholders.map(s => ({
      ...s,
      percentage: Math.round((s.shares / this.totalShares) * 10000) / 100, // Round to 2 decimal places
    }));
  }
  this.lastUpdated = new Date();
  next();
});

// ============================================
// MODEL
// ============================================

export const CapTable: Model<ICapTable> =
  models.CapTable || mongoose.model<ICapTable>('CapTable', CapTableSchema);

export default CapTable;