import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Schema as MongooseSchema, Types } from 'mongoose';
import { CommissionType } from 'src/product/schema/product.schema';

export enum PremiumFrequency {
    ONE_TIME = 'ONE_TIME',
    MONTHLY = 'MONTHLY',
    QUARTERLY = 'QUARTERLY',
    ANNUALLY = 'ANNUALLY'
}

export enum PolicyStatus {
    ACTIVE = 'ACTIVE',
    CANCELLED = 'CANCELLED'
}

// Shown to clients: ACTIVE and CANCELLED are stored, EXPIRED is derived from expiry_date.
export enum PolicyDisplayStatus {
    ACTIVE = 'ACTIVE',
    EXPIRED = 'EXPIRED',
    CANCELLED = 'CANCELLED'
}

export enum CommissionStatus {
    NOT_APPLICABLE = 'NOT_APPLICABLE', // handled by salaried Policy Staff
    PENDING = 'PENDING',
    PAID = 'PAID',
    CANCELLED = 'CANCELLED'
}

export enum InsuredRelation {
    SELF = 'SELF',
    SPOUSE = 'SPOUSE',
    SON = 'SON',
    DAUGHTER = 'DAUGHTER',
    FATHER = 'FATHER',
    MOTHER = 'MOTHER',
    FATHER_IN_LAW = 'FATHER_IN_LAW',
    MOTHER_IN_LAW = 'MOTHER_IN_LAW',
    OTHER = 'OTHER'
}

const InsuredMemberSchema = new MongooseSchema({
    name: { type: String, required: true, trim: true },
    relation: { type: String, enum: Object.values(InsuredRelation), required: true }
}, { _id: false });

@Schema({
    timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
})
export class Policy extends Document {
    @Prop({ type: String, required: true, trim: true, uppercase: true })
    policy_number: string;

    @Prop({ type: Types.ObjectId, ref: 'customers', required: true, index: true })
    customer_id: Types.ObjectId;

    @Prop({ type: Types.ObjectId, ref: 'products', required: true })
    product_id: Types.ObjectId;

    @Prop({ type: String, required: true })
    product_name: string; // snapshot, so renaming a product does not rewrite history

    @Prop({ type: Types.ObjectId, ref: 'categories', required: true, index: true })
    category_id: Types.ObjectId;

    @Prop({ type: Types.ObjectId, ref: 'insurers', required: true, index: true })
    insurer_id: Types.ObjectId;

    @Prop({ type: Types.ObjectId, ref: 'users', required: true, index: true })
    assigned_to: Types.ObjectId; // agent or Policy Staff who handled it

    @Prop({ type: Types.ObjectId, ref: 'leads', default: null })
    lead_id: Types.ObjectId;

    // Financial snapshot taken from the product when the policy was entered.
    @Prop({ type: Number, required: true, min: 0 })
    gross_premium: number;

    @Prop({ type: Number, required: true, min: 0, max: 100 })
    gst_rate: number;

    @Prop({ type: Number, required: true, min: 0 })
    net_premium: number;

    @Prop({ type: Number, required: true, min: 0 })
    gst_amount: number;

    @Prop({ type: String, enum: CommissionType, required: true })
    commission_type: CommissionType;

    @Prop({ type: Number, required: true, min: 0 })
    commission_value: number;

    @Prop({ type: Number, default: null })
    commission_amount: number; // null when not applicable

    @Prop({ type: String, enum: CommissionStatus, required: true })
    commission_status: CommissionStatus;

    @Prop({ type: Number, default: null })
    commission_paid_at: number;

    @Prop({ type: Types.ObjectId, ref: 'users', default: null })
    commission_paid_by: Types.ObjectId;

    @Prop({ type: String, enum: PremiumFrequency, default: PremiumFrequency.ONE_TIME })
    premium_frequency: PremiumFrequency;

    @Prop({ type: Number, default: null, min: 0 })
    sum_insured: number;

    @Prop({ type: String, default: null })
    sum_insured_note: string; // e.g. "Floater"

    @Prop({ type: [InsuredMemberSchema], default: [] })
    insured_members: { name: string; relation: InsuredRelation }[];

    @Prop({ type: String, default: null, uppercase: true, trim: true })
    vehicle_registration: string; // motor policies

    @Prop({ type: Number, required: true })
    issue_date: number;

    @Prop({ type: Number, required: true, index: true })
    expiry_date: number;

    @Prop({ type: MongooseSchema.Types.Mixed, default: null })
    schedule_file: any; // as returned by POST /uploads/file

    @Prop({ type: String, enum: PolicyStatus, default: PolicyStatus.ACTIVE, index: true })
    status: PolicyStatus;

    @Prop({ type: String, default: null })
    cancel_reason: string;

    @Prop({ type: Number, default: null })
    cancelled_at: number;

    @Prop({ type: Types.ObjectId, ref: 'users', default: null })
    created_by: Types.ObjectId;
}

export const PolicySchema = SchemaFactory.createForClass(Policy);
PolicySchema.index({ policy_number: 1 }, { unique: true, collation: { locale: 'en', strength: 2 } });
