File size: 4,300 Bytes
6534ea1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f13b2c
6534ea1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { v4 as uuidv4 } from 'uuid';

export interface ChatMessage {
  id?: number;
  text: string;
  sender: 'user' | 'bot';
  timestamp: Date;
  isTyping?: boolean;
  rawData?: any;
}

export interface SearchResponse {
  success: boolean;
  matched_question?: string;
  answer?: string;
  sno?: number;
  audio_url?: string;
  video_url?: string;
  story_url?: string;
  detail_url?: string;
  example_url?: string;
  confidence_score?: number;
  user_question?: string;
  message?: string;
  suggestion?: string;
  sample_questions?: string[];
  total_questions_available?: number;
  matching_method?: string;
  is_follow_up?: boolean;
  enhanced_question?: string;
  scenario?: string;
  context_info?: {
    current_topic: string | null;
    current_intent: string | null;
    has_context: boolean;
    history_length: number;
  };
}

export interface Question {
  sno: number;
  question: string;
}

@Injectable({
  providedIn: 'root'
})
export class ChatService {

  private readonly apiBase =
    location.hostname.endsWith('hf.space')
      ? 'https://pykara-py-learn-backend.hf.space/staticchat'
      : 'http://localhost:5000/staticchat';

  // =====================================================
  // Static user_id: generated once per browser session.
  // Persists across page navigations within the same tab,
  // but resets when the tab/browser is closed.
  //
  // Options:
  //   sessionStorage  — resets when tab closes (recommended)
  //   localStorage    — persists even after browser restart
  // =====================================================
  private userId: string;

  constructor(private http: HttpClient) {
    // Try to restore existing session ID
    const stored = sessionStorage.getItem('chat_user_id');
    if (stored) {
      this.userId = stored;
    } else {
      // Generate a new one for this session
      this.userId = uuidv4();
      sessionStorage.setItem('chat_user_id', this.userId);
    }
    console.log('Chat session user_id:', this.userId);
  }

  /**
   * Get the current user ID (useful for context endpoints)
   */
  getUserId(): string {
    return this.userId;
  }

  /**
   * Reset the session — clears context on backend and generates a new user_id
   */
  resetSession(): Observable<{ success: boolean; message: string }> {
    const oldUserId = this.userId;

    // Generate new user_id
    this.userId = uuidv4();
    sessionStorage.setItem('chat_user_id', this.userId);
    console.log('Session reset. New user_id:', this.userId);

    // Clear old context on the backend
    return this.http.post<{ success: boolean; message: string }>(
      `${this.apiBase}/context/${oldUserId}/clear`, {}
    );
  }

  /**
   * Search — sends user_id with every request for context carry-forward
   */
  searchQuestion(question: string): Observable<SearchResponse> {
    return this.http.post<SearchResponse>(
      `${this.apiBase}/search`,
      {
        question,
        user_id: this.userId   // <-- This is the key fix
      }
    );
  }

  /**
   * Get all questions for reference / autocomplete
   */
  getAllQuestions(): Observable<{ success: boolean; questions: Question[]; count: number }> {
    return this.http.get<{ success: boolean; questions: Question[]; count: number }>(
      `${this.apiBase}/questions`
    );
  }

  /**
   * Get random suggestions
   */
  getRandomSuggestions(count: number = 5): Observable<{ success: boolean; suggestions: string[] }> {
    return this.http.get<{ success: boolean; suggestions: string[] }>(
      `${this.apiBase}/suggestions`,
      { params: { count: count.toString() } }
    );
  }

  /**
   * Get context-aware follow-up suggestions based on conversation history
   */
  getContextSuggestions(): Observable<{ success: boolean; suggestions: string[]; current_topic: string | null }> {
    return this.http.get<{ success: boolean; suggestions: string[]; current_topic: string | null }>(
      `${this.apiBase}/context/suggestions/${this.userId}`
    );
  }

  /**
   * Get current conversation context (for debugging or UI display)
   */
  getContext(): Observable<any> {
    return this.http.get(`${this.apiBase}/context/${this.userId}`);
  }
}