import { Injectable, HttpException, HttpStatus, Logger } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { User, UserDocument } from './user.schema'

const FREE_OPTIMIZE_LIMIT = 3

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

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

  async checkAndDeductInterview(userId: string) {
    const user = await this.userModel.findById(userId).exec()
    if (!user) throw new HttpException('用户不存在', HttpStatus.NOT_FOUND)
    if (user.plan !== 'free') return

    // Backward compat: migrate remaining → interviewCredits
    if ((user.interviewCredits ?? 0) <= 0 && (user.remaining ?? 0) > 0) {
      await this.userModel.findByIdAndUpdate(userId, {
        $set: { interviewCredits: user.remaining, remaining: 0 },
      }).exec()
    }

    const result = await this.userModel.findOneAndUpdate(
      { _id: userId, interviewCredits: { $gt: 0 } },
      { $inc: { interviewCredits: -1, interviewCount: 1 } },
      { new: true },
    ).exec()
    if (result) return

    // Fallback to share credits
    const shareResult = await this.userModel.findOneAndUpdate(
      { _id: userId, shareCredits: { $gt: 0 } },
      { $inc: { shareCredits: -1, interviewCount: 1 } },
    ).exec()
    if (shareResult) return

    throw new HttpException('面试次数已用完，请购买面试次数或开通会员', HttpStatus.FORBIDDEN)
  }

  async checkAndDeductOptimize(userId: string) {
    const user = await this.userModel.findById(userId).exec()
    if (!user) throw new HttpException('用户不存在', HttpStatus.NOT_FOUND)
    if (user.plan !== 'free') return

    // Try paid credits first
    const paid = await this.userModel.findOneAndUpdate(
      { _id: userId, resumeOptimizeCredits: { $gt: 0 } },
      { $inc: { resumeOptimizeCredits: -1 } },
    ).exec()
    if (paid) return

    // Try old remaining credits (backward compat)
    const oldRemaining = await this.userModel.findOneAndUpdate(
      { _id: userId, remaining: { $gt: 0 } },
      { $inc: { remaining: -1 } },
    ).exec()
    if (oldRemaining) return

    // Then free limit
    const freeResult = await this.userModel.findOneAndUpdate(
      { _id: userId, freeOptimizeUsed: { $lt: FREE_OPTIMIZE_LIMIT } },
      { $inc: { freeOptimizeUsed: 1 } },
    ).exec()
    if (freeResult) return

    // Fallback to share credits
    const shareResult = await this.userModel.findOneAndUpdate(
      { _id: userId, shareCredits: { $gt: 0 } },
      { $inc: { shareCredits: -1 } },
    ).exec()
    if (shareResult) return

    throw new HttpException('简历优化次数已用完，请购买优化次数或开通会员', HttpStatus.FORBIDDEN)
  }

  async grantShareCredits(userId: string, amount = 1): Promise<boolean> {
    const result = await this.userModel.findByIdAndUpdate(
      userId,
      { $inc: { shareCredits: amount } },
    ).exec()
    return !!result
  }

  async checkAndDeductDownload(userId: string, paidDownload: boolean): Promise<boolean> {
    if (paidDownload) return true

    const result = await this.userModel.findOneAndUpdate(
      { _id: userId, resumeDownloadCredits: { $gt: 0 } },
      { $inc: { resumeDownloadCredits: -1 } },
    ).exec()
    return !!result
  }

  async grantCredits(userId: string, type: 'interview' | 'optimize' | 'download', amount: number) {
    if (amount <= 0) throw new HttpException('无效数量', HttpStatus.BAD_REQUEST)

    const fieldMap: Record<string, string> = {
      interview: 'interviewCredits',
      optimize: 'resumeOptimizeCredits',
      download: 'resumeDownloadCredits',
    }
    const field = fieldMap[type]
    if (!field) throw new HttpException('无效类型', HttpStatus.BAD_REQUEST)

    const result = await this.userModel.findByIdAndUpdate(
      userId,
      { $inc: { [field]: amount } },
    ).exec()
    if (!result) throw new HttpException('用户不存在', HttpStatus.NOT_FOUND)
  }

  async setPlanQuota(userId: string, _plan: string, credits: { interview: number; resumeOptimize: number; resumeDownload: number }) {
    const result = await this.userModel.findByIdAndUpdate(userId, {
      $set: {
        remaining: 999,
        interviewCredits: credits.interview,
        resumeOptimizeCredits: credits.resumeOptimize,
        resumeDownloadCredits: credits.resumeDownload,
        freeOptimizeUsed: FREE_OPTIMIZE_LIMIT,
      },
    }).exec()
    if (!result) throw new HttpException('用户不存在', HttpStatus.NOT_FOUND)
  }
}
