import 'dart:convert';
import 'package:http/http.dart' as http;

class OpenAIReceiver {
  final String apiKey;
  final List<Map<String, String>> _messages = [];

  OpenAIReceiver({required this.apiKey});

  Future<String> getResponse(String prompt) async {
    // GPT에게 역할 부여
    // if (_messages.length == 0) {
    _messages.add({
      'role': 'system',
      'content': '''
당신은 구강 건강 관리에 특화된 AI로서, 다음의 전문 역할을 맡고 있습니다:

1. **치과 전문의**: 일반 치아 건강, 진단, 치료 계획에 대한 전문가입니다.
2. **치주염 전문의**: 잇몸 질환, 치주 치료, 잇몸 건강에 대한 전문가입니다.
3. **구내염 전문의**: 구강 점막 질환, 구내염, 염증 등에 대한 전문가입니다.
4. **치위생사**: 예방적인 치과 관리, 스케일링, 구강 위생 교육에 대한 전문가입니다.

당신의 주요 기능은 구강 건강과 관련된 정확하고 전문적인 조언을 제공하는 것입니다. 구강 건강과 관련된 질문이나 주제에만 응답하고, 구강 건강과 관련이 없는 질문에는 응답하지 않습니다. 구강 건강과 무관한 질문에는 다른 전문가에게 문의하도록 안내해 주세요.

구강 건강 관련 질문의 예:
- "치주염 치료를 위한 효과적인 방법은 무엇인가요?"
- "충치를 예방하고 구강 위생을 유지하는 방법은 무엇인가요?"
- "현재 치아의 상태가 어떤가요? 임플란트 비용이 얼마나 될까요?"
구강 건강과 관련이 없는 질문의 예:
- "라자냐를 어떻게 준비하나요?"
- "시력이 많이 떨어진 것 같나요?
- "컴퓨터 견적이 얼마인가요?"
- "피부 미백 레이저 시술해도 괜찮을까요?"
---

당신의 목표는 사용자에게 구강 건강과 관련된 필요를 지원하면서, 전문 역할에 맞는 답변을 제공하는 것입니다.
      ''',
    });
    // }

    // 사용자 메시지를 히스토리에 추가
    _messages.add({
      'role': 'user',
      'content': prompt,
    });

    // 전체 메시지의 토큰 수를 체크하고 필요 시 오래된 메시지를 제거
    if (_calculateTotalTokens(_messages) > 8192) {
      _truncateMessagesToFitTokenLimit();
    }

    final response = await http.post(
      Uri.parse('https://api.openai.com/v1/chat/completions'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $apiKey',
      },
      body: jsonEncode({
        'model': 'gpt-4o', // 모델 버전은 필요에 따라 업데이트하세요.
        'messages': _messages,
        'max_tokens': 800, // 응답의 최대 토큰 수를 설정
      }),
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      final Map<String, dynamic> data = jsonDecode(decodedResponse);
      final String reply = data['choices'][0]['message']['content'].trim();

      // GPT의 응답을 히스토리에 추가
      _messages.add({
        'role': 'assistant',
        'content': reply,
      });

      return reply;
    } else {
      throw Exception('Failed to load OpenAI response');
    }
  }

  Future<String> getResponseFromImage(String ext, String base64Image) async {
    // GPT에게 역할 부여
    // if (_messages.length == 0) {
    _messages.add({
      'role': 'system',
      'content': '''
당신은 비전 AI 입니다.
당신의 주요 기능은 구강 영상을 분석하여, 구강 건강과 관련된 정확하고 전문적인 조언을 제공하는 것입니다.
영상을 구강 의료 관점에서 한글로 전문적으로 묘사합니다.
      ''',
    });
    // }
    // 사용자 메시지를 히스토리에 추가 (이미지 데이터 포함)
    _messages.add({
      'role': 'user',
      'content': jsonEncode({
        'type': 'image',
        'image_url': {'url': 'data:image/jpeg;base64,$base64Image'}
        // 'image_data': 'data:image/png;base64,$base64Image',
      }),
    });

    // 전체 메시지의 토큰 수를 체크하고 필요 시 오래된 메시지를 제거
    if (_calculateTotalTokens(_messages) > 8192) {
      _truncateMessagesToFitTokenLimit();
    }

    final response = await http.post(
      Uri.parse('https://api.openai.com/v1/chat/completions'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $apiKey',
      },
      body: jsonEncode({
        'model': 'gpt-4o-mini', // 모델 버전은 필요에 따라 업데이트하세요.
        'messages': _messages,
        'max_tokens': 2000, // 응답의 최대 토큰 수를 설정
      }),
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      final Map<String, dynamic> data = jsonDecode(decodedResponse);
      final String reply = data['choices'][0]['message']['content'].trim();

      // GPT의 응답을 히스토리에 추가
      _messages.add({
        'role': 'assistant',
        'content': reply,
      });

      return reply;
    } else {
      throw Exception('Failed to load OpenAI response');
    }
  }

  int _calculateTotalTokens(List<Map<String, String>> messages) {
    // 각 메시지의 토큰 수를 계산하여 총 토큰 수를 반환하는 함수
    // 단순히 문자열 길이를 사용한 예제이며, 실제로는 더 정교한 계산 필요
    return messages.fold(
        0, (total, message) => total + message['content']!.length);
  }

  void _truncateMessagesToFitTokenLimit() {
    // 토큰 수를 제한하기 위해 오래된 메시지를 제거하는 함수
    while (_calculateTotalTokens(_messages) > 8192) {
      _messages.removeAt(0);
    }
  }

  // 채팅 히스토리를 초기화하는 메서드
  // void clearHistory() {
  //   _messages.clear();
  // }
}
