import { Controller, Get, Post, Query, UseGuards, Body, HttpException, HttpStatus } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard'
import { CurrentUser } from '../../common/decorators/current-user.decorator'
import { Progress, ProgressDocument } from '../schemas/progress.schema'
import { Interview, InterviewDocument } from '../interview/interview.schema'
import { BenchmarkService, PositionBenchmark } from './benchmark.service'
import { User, UserDocument } from '../user/user.schema'

const REDEEM_ITEMS = {
  extraInterview: { name: '额外面试次数 +1', cost: 30, effect: 'remaining+1' },
  streakFreeze: { name: '补签卡', cost: 20, effect: 'streak_freeze' },
  vipDiscount: { name: '会员 8 折券', cost: 100, effect: 'vip_discount' },
} as const

const DIM_KEYS = ['logic', 'expression', 'professionalism', 'stability'] as const

@Controller('progress')
@UseGuards(JwtAuthGuard)
export class ProgressController {
  constructor(
    @InjectModel(Progress.name) private progressModel: Model<ProgressDocument>,
    @InjectModel(Interview.name) private interviewModel: Model<InterviewDocument>,
    @InjectModel(User.name) private userModel: Model<UserDocument>,
    private readonly benchmarkService: BenchmarkService,
  ) {}

  @Get()
  async getProgress(@CurrentUser('userId') userId: string) {
    let progress = await this.progressModel.findOne({ userId }).exec()
    if (!progress) {
      progress = await this.progressModel.create({
        userId,
        totalInterviews: 0,
        completedInterviews: 0,
        streak: 0,
        points: 0,
        totalCheckins: 0,
        recentScores: [],
        streakHistory: [],
      })
    }

    const recentInterviews = await this.interviewModel
      .find({ userId, status: 'completed' })
      .sort({ createdAt: -1 })
      .limit(10)
      .select('position totalScore questionCount createdAt')
      .exec()

    const today = new Date()
    const todayStr = today.toISOString().slice(0, 10)
    const lastCheckinStr = progress.lastCheckinDate
      ? new Date(progress.lastCheckinDate).toISOString().slice(0, 10)
      : ''
    const checkedToday = todayStr === lastCheckinStr

    return {
      totalInterviews: progress.totalInterviews,
      completedInterviews: progress.completedInterviews,
      dimensions: {
        logic: progress.avgLogic || Math.round(60 + Math.random() * 20),
        expression: progress.avgExpression || Math.round(60 + Math.random() * 20),
        professionalism: progress.avgProfessionalism || Math.round(60 + Math.random() * 20),
        stability: progress.avgStability || Math.round(60 + Math.random() * 20),
      },
      streak: progress.streak,
      points: progress.points || 0,
      totalCheckins: progress.totalCheckins || 0,
      checkedToday,
      lastInterviewDate: progress.lastInterviewDate,
      recentScores: progress.recentScores.slice(-5),
      interviews: recentInterviews.map(i => ({
        id: i._id.toString(),
        position: i.position,
        totalScore: i.totalScore,
        questionCount: i.questionCount,
        date: i.createdAt,
      })),
    }
  }

  // P4: Daily check-in
  @Post('checkin')
  async checkin(@CurrentUser('userId') userId: string) {
    let progress = await this.progressModel.findOne({ userId }).exec()
    if (!progress) {
      progress = await this.progressModel.create({ userId, streak: 0, points: 0, totalCheckins: 0, recentScores: [], streakHistory: [] })
    }

    const today = new Date()
    const todayStr = today.toISOString().slice(0, 10)
    const lastStr = progress.lastCheckinDate
      ? new Date(progress.lastCheckinDate).toISOString().slice(0, 10)
      : ''

    if (todayStr === lastStr) {
      throw new HttpException('今日已打卡', HttpStatus.BAD_REQUEST)
    }

    // Calculate streak continuity
    const yesterday = new Date(today)
    yesterday.setDate(yesterday.getDate() - 1)
    const yesterdayStr = yesterday.toISOString().slice(0, 10)
    const isConsecutive = lastStr === yesterdayStr || !progress.lastCheckinDate

    const newStreak = isConsecutive ? (progress.streak || 0) + 1 : 1
    const bonusPoints = newStreak % 7 === 0 ? 10 : 5

    progress.streak = newStreak
    progress.points = (progress.points || 0) + bonusPoints
    progress.totalCheckins = (progress.totalCheckins || 0) + 1
    progress.lastCheckinDate = today
    progress.streakHistory.push(today)
    await progress.save()

    return {
      streak: newStreak,
      points: progress.points,
      bonusPoints,
      checkedIn: true,
      message: isConsecutive ? `🔥 连续打卡 ${newStreak} 天，获得 ${bonusPoints} 积分` : `打卡成功，获得 ${bonusPoints} 积分`,
    }
  }

  // P4: Redeem points
  @Post('redeem')
  async redeem(@CurrentUser('userId') userId: string, @Body('item') item: string) {
    const redeemItem = REDEEM_ITEMS[item as keyof typeof REDEEM_ITEMS]
    if (!redeemItem) throw new HttpException('无效兑换项目', HttpStatus.BAD_REQUEST)

    const progress = await this.progressModel.findOne({ userId }).exec()
    if (!progress || (progress.points || 0) < redeemItem.cost) {
      throw new HttpException('积分不足', HttpStatus.BAD_REQUEST)
    }

    progress.points = (progress.points || 0) - redeemItem.cost
    await progress.save()

    if (redeemItem.effect === 'remaining+1') {
      await this.userModel.findByIdAndUpdate(userId, { $inc: { remaining: 1 } }).exec()
    }

    return { success: true, points: progress.points, item: redeemItem.name, message: `兑换成功，消耗 ${redeemItem.cost} 积分` }
  }

  // P5: Position match prediction
  @Post('match')
  async matchPosition(@CurrentUser('userId') userId: string, @Body('targetPosition') targetPosition?: string) {
    const progress = await this.progressModel.findOne({ userId }).exec()
    if (!progress || progress.completedInterviews === 0) {
      throw new HttpException('暂无面试数据', HttpStatus.BAD_REQUEST)
    }

    const userDims = {
      logic: progress.avgLogic || 0,
      expression: progress.avgExpression || 0,
      professionalism: progress.avgProfessionalism || 0,
      stability: progress.avgStability || 0,
    }

    const allBenchmarks = await this.benchmarkService.getBenchmark()
    const positions = Object.keys(allBenchmarks).length > 0
      ? Object.keys(allBenchmarks)
      : ['前端工程师', '后端工程师', 'AI算法工程师', '产品经理', '数据分析师', 'UI/UX设计师', '运营', '测试工程师']

    const matches: Array<{
      position: string
      matchScore: number
      dimGaps: Record<string, number>
      level: string
    }> = []

    for (const pos of positions) {
      const bmData = await this.benchmarkService.getBenchmark(pos)
      const bm = 'p50' in bmData ? (bmData as PositionBenchmark).p50 : { logic: 70, expression: 70, professionalism: 70, stability: 70 }

      const dimGaps: Record<string, number> = {}
      let totalGap = 0
      for (const key of DIM_KEYS) {
        const gap = Math.max(0, bm[key] - userDims[key])
        dimGaps[key] = Math.round(gap)
        totalGap += gap
      }

      const maxGap = 120 // 四维满分差 (4 * 30)
      const matchScore = Math.max(0, Math.min(100, Math.round(100 - (totalGap / maxGap) * 100)))
      const level = matchScore >= 85 ? '高度匹配' : matchScore >= 70 ? '较匹配' : matchScore >= 50 ? '一般' : '需提升'

      if (targetPosition && pos !== targetPosition) continue
      matches.push({ position: pos, matchScore, dimGaps, level })
    }

    matches.sort((a, b) => b.matchScore - a.matchScore)

    if (targetPosition && matches.length === 1) {
      return { targetPosition: matches[0], allPositions: null }
    }

    return {
      allPositions: matches.slice(0, 5),
      topMatch: matches[0],
      userDimensions: userDims,
    }
  }

  @Get('benchmark')
  async getBenchmark(
    @CurrentUser('userId') userId: string,
    @Query('position') position?: string,
  ) {
    const result = await this.benchmarkService.getUserPercentile(userId, position)
    if (!result) {
      return { message: '暂无面试数据，请先完成模拟面试', percentile: null, userScores: null, benchmark: null }
    }
    return result
  }

  @Get('benchmark/all')
  async getAllBenchmarks() {
    return this.benchmarkService.getBenchmark()
  }

  @Get('stats')
  async getStats(@CurrentUser('userId') userId: string) {
    const progress = await this.progressModel.findOne({ userId }).exec()
    if (!progress) {
      return { totalInterviews: 0, completedInterviews: 0, avgScore: 0, streak: 0 }
    }

    const completedInterviews = await this.interviewModel
      .find({ userId, status: 'completed' })
      .select('totalScore')
      .exec()

    const avgScore = completedInterviews.length > 0
      ? Math.round(completedInterviews.reduce((s, i) => s + i.totalScore, 0) / completedInterviews.length)
      : 0

    return {
      totalInterviews: progress.totalInterviews,
      completedInterviews: progress.completedInterviews,
      avgScore,
      streak: progress.streak,
      dimensions: {
        logic: progress.avgLogic || 0,
        expression: progress.avgExpression || 0,
        professionalism: progress.avgProfessionalism || 0,
        stability: progress.avgStability || 0,
      },
    }
  }
}