import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
import { HydratedDocument, Types } from 'mongoose'

export type FlagDocument = HydratedDocument<Flag>

export type FlagState = 'off' | 'targeted' | 'rollout' | 'on'

// Embedded change log on the flag itself. Capped to the last 20 entries via a
// guard in FlagsService — keeps the doc small and the side-panel render fast.
export interface FlagHistoryEntry {
  at: Date
  byUserId?: Types.ObjectId
  byEmail?: string
  action: string  // e.g. 'created', 'state: off → rollout', 'pct: 25 → 50'
  note?: string
}

@Schema({ collection: 'flags', timestamps: true })
export class Flag {
  // snake_case identifier used in code paths. Same regex as TenantPlan/slug-ish
  // — keeps it greppable and unambiguous in audit messages.
  @Prop({ required: true, unique: true, index: true, lowercase: true, trim: true })
  key!: string

  // Human label shown in the UI. Optional but recommended.
  @Prop({ default: '' })
  description!: string

  @Prop({ enum: ['off', 'targeted', 'rollout', 'on'], default: 'off', index: true })
  state!: FlagState

  // Only consulted when state === 'rollout'. Hash-based assignment to a bucket
  // (see FlagsService.evaluate) means a given tenant either is or isn't in the
  // rollout — flipping the pct only changes the new slice, not existing ones.
  @Prop({ default: 0, min: 0, max: 100 })
  pct!: number

  // Targeting axes. All optional; empty/missing = "no restriction on this axis".
  // For state === 'targeted' / 'rollout', a tenant must match every non-empty
  // axis to be eligible (intersection, not union).
  @Prop({
    type: {
      plans: { type: [String], default: [] },
      tenantSlugs: { type: [String], default: [] },
      partnerSlugs: { type: [String], default: [] },
      environments: { type: [String], default: [] },
    },
    default: () => ({ plans: [], tenantSlugs: [], partnerSlugs: [], environments: [] }),
  })
  scope!: {
    plans: string[]
    tenantSlugs: string[]
    partnerSlugs: string[]
    environments: string[]
  }

  @Prop({ type: Types.ObjectId, ref: 'User' })
  createdBy?: Types.ObjectId

  // Capped at last 20 in FlagsService.recordHistory.
  @Prop({
    type: [
      {
        at: { type: Date, default: () => new Date() },
        byUserId: { type: Types.ObjectId, ref: 'User' },
        byEmail: String,
        action: { type: String, required: true },
        note: String,
      },
    ],
    default: [],
  })
  history!: FlagHistoryEntry[]
}

export const FlagSchema = SchemaFactory.createForClass(Flag)
