import { Injectable, Logger, HttpException, HttpStatus } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { InterviewReview, InterviewReviewDocument } from './interview-review.schema'
import { AiService } from '../ai/ai.service'
import { AsrService } from './asr.service'
import { analyzeSpeech } from '../../common/utils/filler-words'
import * as fs from 'fs'
import * as path from 'path'

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

  constructor(
    @InjectModel(InterviewReview.name) private reviewModel: Model<InterviewReviewDocument>,
    private aiService: AiService,
    private asrService: AsrService,
  ) {}

  async create(
    userId: string,
    position: string,
    company?: string,
    audioFile?: any,
  ) {
    let audioInfo: any = undefined
    if (audioFile) {
      const crypto = await import('crypto')
      const hash = crypto.createHash('md5').update(audioFile.buffer).digest('hex')
      audioInfo = {
        hash,
        filePath: audioFile.path,
        duration: 0,
        size: audioFile.size,
        mimeType: audioFile.mimetype,
      }
    }

    const review = new this.reviewModel({
      userId,
      position,
      company: company || '',
      status: 'processing',
      audioFile: audioInfo,
    })

    const saved = await review.save()

    // Start async processing (non-blocking)
    this.processReview(saved._id.toString()).catch((err) => {
      this.logger.error(`Review ${saved._id} processing failed: ${err.message}`)
    })

    return {
      id: saved._id.toString(),
      status: 'processing',
      estimatedTime: 120,
    }
  }

  /** Create from text transcript (skip ASR, go straight to analysis) */
  async createFromText(
    userId: string,
    position: string,
    text: string,
    company?: string,
  ) {
    const review = new this.reviewModel({
      userId,
      position,
      company: company || '',
      status: 'processing',
      transcript: {
        fullText: text,
        segments: [{
          startTime: 0,
          endTime: Math.max(text.length / 3.5, 10),
          speaker: 'candidate',
          text,
        }],
      },
    })

    const saved = await review.save()

    this.processReview(saved._id.toString()).catch((err) => {
      this.logger.error(`Review ${saved._id} processing failed: ${err.message}`)
    })

    return {
      id: saved._id.toString(),
      status: 'processing',
      estimatedTime: 60,
    }
  }

  async processReview(reviewId: string) {
    const review = await this.reviewModel.findById(reviewId)
    if (!review) {
      throw new Error('Review not found')
    }

    try {
      // Step 1: ASR (if audio file exists and no transcript yet)
      let transcript = review.transcript
      if (!transcript && review.audioFile?.filePath) {
        const asrResult = await this.asrService.transcribe(
          review.audioFile.filePath,
          review.audioFile.mimeType,
        )
        transcript = {
          fullText: asrResult.fullText,
          segments: asrResult.segments.map(s => ({
            startTime: s.startTime,
            endTime: s.endTime,
            speaker: s.speaker as 'interviewer' | 'candidate',
            text: s.text,
          })),
        }
        await this.reviewModel.findByIdAndUpdate(reviewId, { transcript })
      }

      const transcriptText = transcript?.fullText || ''

      // Step 2: Speech analysis (filler words)
      const speechResult = analyzeSpeech(transcriptText)
      let pace = '适中'
      const rate = speechResult.speechRate
      if (rate > 5) pace = '偏快'
      else if (rate < 2.5) pace = '偏慢'

      const speechAnalysis = {
        fillerWords: speechResult.fillerWords,
        fillerScore: speechResult.fillerScore,
        fillerDensity: speechResult.fillerDensity,
        pace,
        totalDuration: speechResult.estimatedDurationSec,
        totalChars: speechResult.totalChars,
      }

      // Step 3: AI analysis
      const analysis = await this.runAiAnalysis(transcriptText, review.position, review.company)

      // Save results
      await this.reviewModel.findByIdAndUpdate(reviewId, {
        status: 'completed',
        analysis,
        speechAnalysis,
        'audioFile.duration': speechResult.estimatedDurationSec,
      })
    } catch (err: any) {
      this.logger.error(`Processing failed for review ${reviewId}: ${err.message}`)
      await this.reviewModel.findByIdAndUpdate(reviewId, {
        status: 'failed',
        $inc: { retryCount: 1 },
      })
    }
  }

  private async runAiAnalysis(transcriptText: string, position: string, company: string) {
    if (!transcriptText.trim()) {
      return this.emptyAnalysis()
    }

    const systemPrompt = `你是一位资深的校招面试评估专家。分析以下面试转录内容，输出评估报告。

评估维度（0-100分）：
1. 逻辑思维(logic)：回答是否结构化、层次分明、有因果关系
2. 表达能力(expression)：语言是否流畅、用词是否准确、表达是否清晰
3. 专业度(professionalism)：技术栈掌握程度、行业认知深度、术语使用是否准确
4. 临场稳定性(stability)：面对问题是否沉着、反应速度、抗压能力

输出格式（严格的 JSON，不要多余内容）：
{
  "overallScore": 0-100,
  "dimensions": { "logic": 0-100, "expression": 0-100, "professionalism": 0-100, "stability": 0-100 },
  "strengths": ["亮点1", "亮点2"],
  "weaknesses": ["不足1", "不足2"],
  "suggestions": ["改进建议1", "改进建议2"],
  "questionBreakdown": [
    {
      "question": "面试官的问题",
      "answer": "用户的回答摘要",
      "score": 0-100,
      "comment": "简短评语",
      "suggestedAnswer": "参考回答思路"
    }
  ]
}`

    const companyStr = company ? `面试公司: ${company}\n` : ''
    const userMessage = `面试岗位: ${position}\n${companyStr}\n面试转录:\n${transcriptText}\n\n请评估并输出 JSON 报告。`

    try {
      const result = await this.aiService.call({
        systemPrompt,
        userMessage,
        temperature: 0.5,
        maxTokens: 2048,
      })
      const parsed = JSON.parse(result)

      // Validate required fields
      if (!parsed.overallScore || !parsed.dimensions) {
        return this.emptyAnalysis()
      }

      return {
        overallScore: Math.min(100, Math.max(0, Math.round(parsed.overallScore))),
        dimensions: {
          logic: Math.min(100, Math.max(0, Math.round(parsed.dimensions.logic || 0))),
          expression: Math.min(100, Math.max(0, Math.round(parsed.dimensions.expression || 0))),
          professionalism: Math.min(100, Math.max(0, Math.round(parsed.dimensions.professionalism || 0))),
          stability: Math.min(100, Math.max(0, Math.round(parsed.dimensions.stability || 0))),
        },
        strengths: Array.isArray(parsed.strengths) ? parsed.strengths : [],
        weaknesses: Array.isArray(parsed.weaknesses) ? parsed.weaknesses : [],
        suggestions: Array.isArray(parsed.suggestions) ? parsed.suggestions : [],
        questionBreakdown: Array.isArray(parsed.questionBreakdown) ? parsed.questionBreakdown.slice(0, 10) : [],
      }
    } catch {
      return this.emptyAnalysis()
    }
  }

  private emptyAnalysis() {
    return {
      overallScore: 60,
      dimensions: { logic: 60, expression: 60, professionalism: 60, stability: 60 },
      strengths: ['转录文本为空或 AI 分析异常'],
      weaknesses: ['请检查音频文件或重新上传'],
      suggestions: ['确保录音清晰完整后重新提交'],
      questionBreakdown: [],
    }
  }

  async getDetail(reviewId: string, userId: string) {
    const review = await this.reviewModel.findById(reviewId).lean()
    if (!review) {
      throw new HttpException('复盘记录不存在', HttpStatus.NOT_FOUND)
    }
    if (review.userId.toString() !== userId) {
      throw new HttpException('无权访问', HttpStatus.FORBIDDEN)
    }
    return this.sanitize(review)
  }

  async listByUser(userId: string, page = 1, limit = 20) {
    const skip = (page - 1) * limit
    const [items, total] = await Promise.all([
      this.reviewModel
        .find({ userId })
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(limit)
        .select('-transcript.fullText -transcript.segments')
        .lean(),
      this.reviewModel.countDocuments({ userId }),
    ])
    return {
      items: items.map(i => this.sanitize(i)),
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    }
  }

  async delete(reviewId: string, userId: string) {
    const review = await this.reviewModel.findById(reviewId)
    if (!review) {
      throw new HttpException('复盘记录不存在', HttpStatus.NOT_FOUND)
    }
    if (review.userId.toString() !== userId) {
      throw new HttpException('无权删除', HttpStatus.FORBIDDEN)
    }

    // Delete audio file if exists
    if (review.audioFile?.filePath) {
      try {
        fs.unlinkSync(review.audioFile.filePath)
      } catch {
        // ignore
      }
    }

    await this.reviewModel.findByIdAndDelete(reviewId)
    return { success: true }
  }

  private sanitize(item: any) {
    if (!item) return item
    const obj = { ...item }
    // Remove sensitive fields
    if (obj.audioFile?.filePath) {
      obj.audioFile = { ...obj.audioFile }
      delete obj.audioFile.filePath
    }
    return obj
  }
}
