File size: 3,021 Bytes
92a138e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
const aiService = require('../services/aiService');
const localAtsService = require('../services/localAtsService');
const logger = require('../config/logger');

/**
 * Scan Resume - Hybrid Approach
 * Uses local rules for the core score (FREE) and AI for deeper insights if needed.
 */
exports.scanResume = async (req, res) => {
  try {
    const { resumeData, useAi = false, jobDescription = '', targetJob = '' } = req.body;
    if (!resumeData) {
      return res.status(400).json({ success: false, message: 'resumeData is required' });
    }

    // 1. Always do local analysis (FAST & FREE)
    const localResult = localAtsService.analyze(resumeData);

    // 2. If user wants AI "Deep Scan", merge results
    if (useAi) {
      try {
        const aiResult = await aiService.analyzeAts(resumeData, jobDescription, targetJob);
        // Add AI results to the response
        localResult.aiScore = aiResult.score;
        localResult.aiGrade = aiResult.grade;
        localResult.aiFeedback = aiResult.feedback;
        localResult.topImprovements = aiResult.topImprovements || localResult.topImprovements;
      } catch (aiErr) {
        logger.error(`AI Deep Scan failed: ${aiErr.message}`);
      }
    }

    res.json({ success: true, data: localResult });
  } catch (error) {
    logger.error(`ATS Scan Error: ${error.message}`);
    res.status(500).json({ success: false, message: error.message });
  }
};

exports.translateResume = async (req, res) => {
  try {
    const { resumeData, language } = req.body;
    if (!resumeData || !language) {
      return res.status(400).json({ success: false, message: 'resumeData and language are required' });
    }
    const result = await aiService.translateResume(resumeData, language);
    res.json({ success: true, data: result });
  } catch (error) {
    logger.error(`Translation Error: ${error.message}`);
    res.status(500).json({ success: false, message: error.message });
  }
};


exports.generateSuggestion = async (req, res) => {
  try {
    const { type, context, stream = false } = req.body;
    if (!type || !context) {
      return res.status(400).json({ success: false, message: 'type and context are required' });
    }

    if (stream) {
      res.setHeader('Content-Type', 'text/event-stream');
      res.setHeader('Cache-Control', 'no-cache');
      res.setHeader('Connection', 'keep-alive');

      await aiService.generateSuggestionStream(type, context, (chunk) => {
        res.write(`data: ${JSON.stringify({ chunk })}\n\n`);
      });

      res.write('data: [DONE]\n\n');
      return res.end();
    }

    const result = await aiService.generateSuggestion(type, context);
    res.json({ success: true, data: result });
  } catch (error) {
    logger.error(`AI Suggestion Error: ${error.message}`, { stack: error.stack });
    if (!res.headersSent) {
      res.status(500).json({ success: false, message: error.message });
    } else {
      res.write(`data: ${JSON.stringify({ error: error.message })}\n\n`);
      res.end();
    }
  }
};