import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
import { BaseEntity } from '../../common/entities/base.entity';
import { SubFee, SubFeeSchema } from './fee-structure.schema';

export type FeeAssignmentDocument = FeeAssignment & Document;

@Schema({ timestamps: true })
export class FeeAssignment extends BaseEntity {
    @Prop({ required: true }) studentId: string;
    @Prop({ required: true }) feeStructureId: string;
    @Prop({ required: true }) academicYearId: string;
    @Prop({ required: true }) classId: string;

    @Prop({ required: true, trim: true }) feeName: string;
    @Prop({ required: true, trim: true }) installment: string;

    // `amount` is the TOTAL due (baseAmount + Σ subFees). All payment/fine/discount
    // math reads from here. baseAmount + subFees are denormalized from the parent
    // FeeStructure at generation/regen time for invoice/modal breakdown display.
    @Prop({ required: true, min: 0 }) amount: number;
    @Prop({ default: 0, min: 0 }) baseAmount: number;
    @Prop({ type: [SubFeeSchema], default: [] }) subFees: SubFee[];
    @Prop({ default: 0, min: 0 }) fineAmount: number;
    @Prop({ default: 0, min: 0 }) paidAmount: number;
    @Prop({ required: true }) dueDate: Date;

    @Prop({ required: true, enum: ['pending', 'partial', 'paid'], default: 'pending' })
    status: 'pending' | 'partial' | 'paid';

    // Discount
    @Prop({ enum: ['amount', 'percentage'] }) discountType?: 'amount' | 'percentage';
    @Prop({ min: 0 }) discountValue?: number;
    @Prop({ default: 0, min: 0 }) discountAmount: number;
    @Prop({ trim: true, maxlength: 500 }) discountReason?: string;
    @Prop() discountValidUntil?: Date;
    @Prop() discountAppliedBy?: string;

    // Payment
    @Prop() paidAt?: Date;
    @Prop({ enum: ['razorpay', 'cash', 'cheque', 'bank_transfer', 'upi', 'online'] })
    paymentMethod?: string;
    @Prop({ trim: true }) receiptNumber?: string;
    @Prop() razorpayOrderId?: string;
    @Prop() razorpayPaymentId?: string;
    @Prop() razorpaySignature?: string;
    @Prop({ min: 0 }) razorpayOrderAmount?: number;
    @Prop() collectedBy?: string;
    @Prop({ trim: true }) notes?: string;
    @Prop({ trim: true, maxlength: 200 }) transactionId?: string;
}

export const FeeAssignmentSchema = SchemaFactory.createForClass(FeeAssignment);
FeeAssignmentSchema.index({ studentId: 1, academicYearId: 1 });
FeeAssignmentSchema.index({ feeStructureId: 1 });
FeeAssignmentSchema.index({ academicYearId: 1, classId: 1, status: 1 });
FeeAssignmentSchema.index({ status: 1, dueDate: 1 });
FeeAssignmentSchema.index({ razorpayOrderId: 1 }, { unique: true, sparse: true });
FeeAssignmentSchema.index({ receiptNumber: 1 }, { unique: true, sparse: true });
FeeAssignmentSchema.index({ studentId: 1, feeStructureId: 1, installment: 1 }, { unique: true });
FeeAssignmentSchema.set('toJSON', { versionKey: false });
FeeAssignmentSchema.set('toObject', { versionKey: false });
