import { Injectable, Logger } from '@nestjs/common'
import { Cron, CronExpression } from '@nestjs/schedule'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { User, UserDocument } from '../user/user.schema'
import { PricingService } from '../schemas/pricing.service'
import { GravityTransaction } from '../schemas/gravity-transaction.schema'

@Injectable()
export class GravityTopUpService {
  private readonly logger = new Logger(GravityTopUpService.name)

  constructor(
    @InjectModel(User.name) private userModel: Model<UserDocument>,
    @InjectModel(GravityTransaction.name) private gravityTxModel: Model<GravityTransaction>,
    private pricingService: PricingService,
  ) {}

  private async logBulkTopUp(userIds: string[], amount: number, type: string) {
    const users = await this.userModel.find({ _id: { $in: userIds } }).select('gravity').exec()
    const docs = users.map(u => ({
      userId: u._id.toString(),
      amount,
      balance: u.gravity,
      type,
      description: `月度补给 ${amount} 引力值`,
    }))
    if (docs.length > 0) {
      await this.gravityTxModel.insertMany(docs)
    }
  }

  @Cron(CronExpression.EVERY_DAY_AT_2AM)
  async topUpVipGravity() {
    this.logger.log('Topping up gravity for active VIP members...')
    const pricing = await this.pricingService.getConfig()
    const now = new Date()

    // 成长版 —— vipExpireAt 未过期
    const growthPlan = pricing.plans.growth
    const growthUsers = await this.userModel.find(
      { plan: 'growth', vipExpireAt: { $gt: now } },
    ).select('_id').exec()
    const growthIds = growthUsers.map(u => u._id.toString())
    if (growthIds.length > 0) {
      await this.userModel.updateMany(
        { _id: { $in: growthIds } },
        { $inc: { gravity: growthPlan.gravityPerMonth } },
      ).exec()
      await this.logBulkTopUp(growthIds, growthPlan.gravityPerMonth, 'monthly_topup')
      this.logger.log(`Growth plan: topped up ${growthIds.length} users with ${growthPlan.gravityPerMonth} gravity each`)
    }

    // 冲刺版 —— sprintExpireAt 未过期
    const sprintPlan = pricing.plans.sprint
    const sprintUsers = await this.userModel.find(
      { plan: 'sprint', sprintExpireAt: { $gt: now } },
    ).select('_id').exec()
    const sprintIds = sprintUsers.map(u => u._id.toString())
    if (sprintIds.length > 0) {
      await this.userModel.updateMany(
        { _id: { $in: sprintIds } },
        { $inc: { gravity: sprintPlan.gravityPerMonth } },
      ).exec()
      await this.logBulkTopUp(sprintIds, sprintPlan.gravityPerMonth, 'monthly_topup')
      this.logger.log(`Sprint plan: topped up ${sprintIds.length} users with ${sprintPlan.gravityPerMonth} gravity each`)
    }
  }
}
