import { Injectable, HttpException, HttpStatus, Logger } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { Interview, InterviewDocument } from './interview.schema'
import { Progress, ProgressDocument } from '../schemas/progress.schema'
import { AiService } from '../ai/ai.service'
import { UserService } from '../user/user.service'
import { QuotaService } from '../user/quota.service'
import { TtsService } from '../tts/tts.service'
import { analyzeSpeech } from '../../common/utils/filler-words'

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

  constructor(
    @InjectModel(Interview.name) private interviewModel: Model<InterviewDocument>,
    @InjectModel(Progress.name) private progressModel: Model<ProgressDocument>,
    private aiService: AiService,
    private userService: UserService,
    private quotaService: QuotaService,
    private ttsService: TtsService,
  ) {}

  async create(userId: string, position: string) {
    // Step 1: 先检查引力值是否足够（不扣除）
    const cost = await this.quotaService.checkInterview(userId)

    // Step 2: AI 生成第一个问题
    let firstQuestion: string
    try {
      firstQuestion = await this.aiService.call({
        systemPrompt: `你是一位专业的${position}面试官。请针对校招该岗位提出第一个面试问题，要求具体且有针对性。直接输出问题，不要多余内容。`,
        userMessage: `请为${position}岗位的校招候选人提出第一个面试问题。`,
        temperature: 0.8,
      })
    } catch (e) {
      this.logger.error(`AI call failed for interview create: ${(e as Error).message}`)
      throw new HttpException('AI 服务暂时不可用，请稍后重试', HttpStatus.SERVICE_UNAVAILABLE)
    }

    // Step 3: AI 调用成功后，扣除引力值并创建面试记录
    await this.quotaService.deductInterview(userId, cost)

    const interview = await this.interviewModel.create({
      userId,
      position,
      messages: [{ role: 'ai', content: firstQuestion }],
      questionCount: 1,
    })

    return {
      id: interview._id.toString(),
      position: interview.position,
      messages: interview.messages,
      questionCount: interview.questionCount,
    }
  }

  async answer(interviewId: string, userId: string, answer: string) {
    const interview = await this.interviewModel.findOne({ _id: interviewId, userId }).exec()
    if (!interview) throw new HttpException('面试不存在', HttpStatus.NOT_FOUND)
    if (interview.status === 'completed') throw new HttpException('面试已结束', HttpStatus.BAD_REQUEST)

    // 检查轮次限制
    const user = await this.userService.getModel().findById(userId).exec()
    const maxRounds = user?.plan !== 'free' ? 10 : 5
    if (interview.questionCount >= maxRounds) {
      throw new HttpException(
        user?.plan !== 'free' ? '已达到每场面试最大轮次（10轮）' : '免费版每场最多5轮，升级会员可享10轮',
        HttpStatus.FORBIDDEN
      )
    }

    // Save user's answer
    interview.messages.push({ role: 'user', content: answer })
    interview.questionCount += 1

    // Analyze filler words in user's answer
    const speechAnalysis = analyzeSpeech(answer)
    interview.fillerWords = speechAnalysis.fillerWords.map(f => ({ word: f.word, count: f.count }))
    interview.fillerScore = speechAnalysis.fillerScore
    interview.fillerDensity = speechAnalysis.fillerDensity

    // AI evaluates answer and generates next question
    const conversationHistory = interview.messages
      .slice(-6)
      .map(m => `${m.role === 'ai' ? '面试官' : '候选人'}: ${m.content}`)
      .join('\n')

    const aiResponse = await this.aiService.call({
      systemPrompt: `你是一位专业的面试官。评估候选人的回答，然后提出下一个问题。
- 如果这已经是第5-8个问题，给出总结性评价并建议结束面试
- 评估要简短，然后立即问下一个问题
- 使用「回答评价：...新的问题：...」的格式。`,
      userMessage: `岗位: ${interview.position}
对话历史:
${conversationHistory}

候选人的回答: ${answer}

请评估并问下一个问题。`,
      temperature: 0.7,
      maxTokens: 1024,
    })

    interview.messages.push({ role: 'ai', content: aiResponse })
    await interview.save()

    return {
      id: interview._id.toString(),
      messages: interview.messages.slice(-2),
      questionCount: interview.questionCount,
    }
  }

  async answerWithAvatar(interviewId: string, userId: string, answer: string) {
    const base = await this.answer(interviewId, userId, answer)
    const aiMsg = base.messages?.find(m => m.role === 'ai')
    if (aiMsg?.content) {
      try {
        const tts = await this.ttsService.synthesize(aiMsg.content)
        return { ...base, ttsHash: tts.hash, ttsDurationMs: tts.durationMs, ttsAmplitude: tts.amplitudeData }
      } catch {
        // TTS failure is non-critical, return without audio
      }
    }
    return base
  }

  async complete(interviewId: string, userId: string) {
    const interview = await this.interviewModel.findOne({ _id: interviewId, userId }).exec()
    if (!interview) throw new HttpException('面试不存在', HttpStatus.NOT_FOUND)
    if (interview.status === 'completed') throw new HttpException('面试已结束', HttpStatus.BAD_REQUEST)

    // Generate final summary with dimension scores
    const fullConversation = interview.messages
      .map(m => `${m.role === 'ai' ? '面试官' : '候选人'}: ${m.content}`)
      .join('\n')

    const summary = await this.aiService.call({
      systemPrompt: `你是一位专业的面试评估师。根据面试对话，生成评估报告。输出JSON格式：
{
  "总体评分": 85,
  "逻辑思维": 80,
  "表达能力": 85,
  "专业度": 90,
  "稳定性": 82,
  "优点": ["逻辑清晰", "举例充分"],
  "不足": ["回答过长", "缺少数据支撑"],
  "建议": ["使用STAR法则", "控制回答时间"]
}`,
      userMessage: `岗位: ${interview.position}

面试记录:
${fullConversation}

请生成评估报告。`,
      temperature: 0.5,
      maxTokens: 2048,
    })

    // Parse summary
    let totalScore = 0
    let dimensions = { logic: 0, expression: 0, professionalism: 0, stability: 0 }
    try {
      const parsed = JSON.parse(summary)
      totalScore = parsed.总体评分 || parsed.score || 0
      dimensions = {
        logic: parsed.逻辑思维 || 0,
        expression: parsed.表达能力 || 0,
        professionalism: parsed.专业度 || 0,
        stability: parsed.稳定性 || 0,
      }
    } catch {
      const match = summary.match(/(\d{1,3})(?=\s*分)/)
      totalScore = match ? parseInt(match[1]) : 0
    }

    interview.status = 'completed'
    interview.totalScore = totalScore
    interview.summary = summary
    await interview.save()

    // === PROGRESS TRACKING ===
    await this.trackProgress(userId, interview._id.toString(), interview.position, totalScore, dimensions)

    return {
      id: interview._id.toString(),
      totalScore,
      summary,
      dimensions,
      questionCount: interview.questionCount,
      position: interview.position,
      contributionPrompt: '分享你的面试经验，帮助更多同学！是否愿意贡献面经？（选填公司名称 + 遇到的面试题）',
    }
  }

  private async trackProgress(
    userId: string,
    interviewId: string,
    position: string,
    totalScore: number,
    dimensions: { logic: number; expression: number; professionalism: number; stability: number },
  ) {
    let progress = await this.progressModel.findOne({ userId }).exec()
    if (!progress) {
      progress = await this.progressModel.create({
        userId,
        totalInterviews: 0,
        completedInterviews: 0,
        recentScores: [],
        streakHistory: [],
      })
    }

    progress.totalInterviews += 1
    progress.completedInterviews += 1

    // Update rolling averages
    const n = progress.completedInterviews
    progress.avgLogic = Math.round(((progress.avgLogic * (n - 1)) + dimensions.logic) / n)
    progress.avgExpression = Math.round(((progress.avgExpression * (n - 1)) + dimensions.expression) / n)
    progress.avgProfessionalism = Math.round(((progress.avgProfessionalism * (n - 1)) + dimensions.professionalism) / n)
    progress.avgStability = Math.round(((progress.avgStability * (n - 1)) + dimensions.stability) / n)

    // Add to recent scores
    progress.recentScores.push({
      interviewId,
      date: new Date(),
      position,
      totalScore,
      dimensions,
    })
    // Keep only last 20
    if (progress.recentScores.length > 20) {
      progress.recentScores = progress.recentScores.slice(-20)
    }

    // === STREAK TRACKING ===
    const today = new Date()
    today.setHours(0, 0, 0, 0)

    if (progress.lastInterviewDate) {
      const lastDate = new Date(progress.lastInterviewDate)
      lastDate.setHours(0, 0, 0, 0)
      const diffDays = Math.floor((today.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24))

      if (diffDays === 1) {
        // Consecutive day
        progress.streak += 1
      } else if (diffDays > 1) {
        // Streak broken
        progress.streak = 1
      }
      // same day = no change
    } else {
      progress.streak = 1
    }

    progress.lastInterviewDate = today
    progress.streakHistory.push(today)

    await progress.save()
  }

  async getDetail(interviewId: string, userId: string) {
    const interview = await this.interviewModel.findOne({ _id: interviewId, userId }).exec()
    if (!interview) throw new HttpException('面试不存在', HttpStatus.NOT_FOUND)

    // Compute aggregate speech analysis from user messages
    const userAnswers = interview.messages
      .filter(m => m.role === 'user')
      .map(m => m.content)
      .join('\n')
    const speechAnalysis = userAnswers ? analyzeSpeech(userAnswers) : null

    // Parse dimensions from summary JSON
    let dimensions: Record<string, number> | null = null
    if (interview.summary) {
      try {
        const parsed = JSON.parse(interview.summary)
        dimensions = {
          logic: parsed['逻辑思维'] || 0,
          expression: parsed['表达能力'] || 0,
          professionalism: parsed['专业度'] || 0,
          stability: parsed['稳定性'] || 0,
        }
      } catch {}
    }

    return {
      ...interview.toObject(),
      fillerWords: speechAnalysis?.fillerWords || interview.fillerWords,
      fillerScore: speechAnalysis?.fillerScore || interview.fillerScore,
      fillerDensity: speechAnalysis?.fillerDensity || interview.fillerDensity,
      speechAnalysis,
      dimensions,
    }
  }

  async getList(userId: string) {
    const interviews = await this.interviewModel
      .find({ userId })
      .sort({ createdAt: -1 })
      .select('position status totalScore questionCount createdAt')
      .exec()

    return interviews.map(i => ({
      id: i._id.toString(),
      position: i.position,
      status: i.status,
      totalScore: i.totalScore,
      questionCount: i.questionCount,
      time: i.createdAt,
    }))
  }

  async getStats(userId: string) {
    const interviews = await this.interviewModel.find({ userId }).exec()
    const completed = interviews.filter(i => i.status === 'completed')
    const totalScore = completed.reduce((s, i) => s + i.totalScore, 0)

    return {
      interviewCount: interviews.length,
      completedCount: completed.length,
      avgScore: completed.length > 0 ? Math.round(totalScore / completed.length) : 0,
    }
  }
}