File size: 6,512 Bytes
24e6f5b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions
from .rag_service import generate_chat_response
from finance.utils_mongo import get_user_db_id
import tempfile
import os
import pdfplumber

class ChatView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        query = request.data.get('message', '')
        provider = request.data.get('provider')
        is_voice = request.data.get('is_voice', False)
        attached_file = request.FILES.get('file')

        # 1. Process PDF Attachment (Text Extraction)
        if attached_file and attached_file.name.lower().endswith('.pdf'):
            try:
                with pdfplumber.open(attached_file) as pdf:
                    pdf_text = ""
                    for page in pdf.pages:
                        pdf_text += (page.extract_text() or "") + "\n"
                    if pdf_text:
                        query = f"[ATTACHED PDF CONTENT: {attached_file.name}]\n{pdf_text}\n\nUSER QUESTION: {query}"
            except Exception as e:
                print(f"PDF extraction error: {e}")

        # 2. Process Image Attachment (Temporary Save for Vision)
        image_path = None
        if attached_file and any(attached_file.name.lower().endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.webp']):
            try:
                suffix = os.path.splitext(attached_file.name)[1]
                with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
                    for chunk in attached_file.chunks():
                        tmp.write(chunk)
                    image_path = tmp.name
            except Exception as e:
                print(f"Image save error: {e}")

        if not query and not image_path:
            return Response({"error": "Message or attachment is required"}, status=status.HTTP_400_BAD_REQUEST)
            
        mongo_user_id = get_user_db_id(request.user)
        auth_header = request.headers.get('Authorization', '')
        access_token = auth_header.replace('Bearer ', '').strip() if auth_header.startswith('Bearer ') else None
        
        if is_voice:
            from finance.ai_helper import generate_voice_response
            result = generate_voice_response(query, provider=provider)
        else:
            result = generate_chat_response(
                mongo_user_id, 
                query, 
                provider=provider, 
                access_token=access_token,
                image_path=image_path
            )
        
        # Cleanup temporary image file
        if image_path and os.path.exists(image_path):
            try:
                os.remove(image_path)
            except:
                pass
        
        # Save to MongoDB (Embedded in User)
        try:
            from expense_tracker.utils import MongoDBClient
            from datetime import datetime
            from bson import ObjectId
            
            db = MongoDBClient.get_client()
            chat_log = {
                '_id': ObjectId(),
                'query': query,
                'response': result.get('response'),
                'context_used': result.get('context_used'),
                'timestamp': datetime.now()
            }
            db.users.update_one(
                {'_id': mongo_user_id},
                {'$push': {'chat_history': chat_log}}
            )
        except Exception as e:
            pass  # Silently fail if chat log saving fails

        return Response(result)

    def get(self, request):
        """Retrieve chat history for the user"""
        try:
            from expense_tracker.utils import MongoDBClient
            from bson import ObjectId
            
            db = MongoDBClient.get_client()
            db = MongoDBClient.get_client()
            mongo_user_id = get_user_db_id(request.user)
            user = db.users.find_one({'_id': mongo_user_id}, {'chat_history': 1})
            
            history = []
            if user and 'chat_history' in user:
                # Return last 50 entries
                raw_history = user['chat_history'][-50:]
                for h in raw_history:
                    # Format for frontend with ID for deletion
                    history.append({
                        'id': str(h.get('_id', '')),
                        'sender': 'user', 
                        'text': h.get('query'),
                        'timestamp': h.get('timestamp')
                    })
                    history.append({
                        'id': str(h.get('_id', '')),
                        'sender': 'bot', 
                        'text': h.get('response'),
                        'timestamp': h.get('timestamp')
                    })
            
            return Response(history)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def delete(self, request, msg_id=None):
        """Delete a specific chat entry from history"""
        if not msg_id:
            return Response({"error": "Message ID required"}, status=status.HTTP_400_BAD_REQUEST)
            
        try:
            from expense_tracker.utils import MongoDBClient
            from bson import ObjectId
            
            db = MongoDBClient.get_client()
            db = MongoDBClient.get_client()
            mongo_user_id = get_user_db_id(request.user)
            if msg_id == 'all':
                result = db.users.update_one(
                    {'_id': mongo_user_id},
                    {'$set': {'chat_history': []}}
                )
                if result.modified_count > 0:
                    return Response({"message": "All chat history cleared"}, status=status.HTTP_200_OK)
                return Response({"message": "No chat history to clear"}, status=status.HTTP_200_OK)

            result = db.users.update_one(
                {'_id': mongo_user_id},
                {'$pull': {'chat_history': {'_id': ObjectId(msg_id)}}}
            )
            
            if result.modified_count > 0:
                return Response({"message": "Chat deleted successfully"}, status=status.HTTP_200_OK)
            else:
                return Response({"error": "Chat not found"}, status=status.HTTP_404_NOT_FOUND)
                
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)