import 'dart:convert';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hoshan/core/utils/strings.dart';
import 'package:hoshan/data/model/ai/ai_response_model.dart';
import 'package:hoshan/data/model/ai/messages_model.dart';
import 'package:hoshan/data/model/ai/send_message_model.dart';
import 'package:hoshan/data/repository/chatbot_repository.dart';
import 'package:string_validator/string_validator.dart';

part 'receive_message_state.dart';

class ReceiveMessageCubit extends Cubit<ReceiveMessageState> {
  ReceiveMessageCubit() : super(ReceiveMessageInitial());

  static ScrollController scrollController = ScrollController();
  static ValueNotifier<bool> onResponse = ValueNotifier(false);

  static Future<void> scrollToEnd({final double? extra}) async {
    try {
      await scrollController.animateTo(
        scrollController.position.minScrollExtent + (extra ?? 0),
        duration: const Duration(milliseconds: 600),
        curve: Curves.easeInOut,
      );
    } catch (e) {
      if (kDebugMode) {
        // print('Error in Scroll:$e');
      }
    }
  }

  static Future<void> scrollToStart({final double? extra}) async {
    try {
      await scrollController.animateTo(
        scrollController.position.maxScrollExtent + (extra ?? 0),
        duration: const Duration(milliseconds: 600),
        curve: Curves.easeInOut,
      );
    } catch (e) {
      if (kDebugMode) {
        // print('Error in Scroll:$e');
      }
    }
  }

  void execute({required final SendMessageModel request}) async {
    emit(ReceiveMessageLoading());
    onResponse.value = true;
    String result = '';
    AiResponseModel aiResponseModel = AiResponseModel();
    await scrollToEnd();
    try {
      await for (String message in request.tool!
          ? ChatbotRepository.sendMessageTool(request)
          : ChatbotRepository.sendMessage(request)) {
        Map<String, dynamic> jsonMap;
        try {
          jsonMap = jsonDecode(message);
        } catch (e) {
          if (kDebugMode) {
            print('Error in Parse: $e');
          }
          jsonMap = {};
          jsonMap['content'] = '';
          try {
            message = message.trim();

            List<String> jsonStrings = message.split('}{').map((s) {
              if (!s.startsWith('{')) s = '{$s';
              if (!s.endsWith('}')) s = '$s}';
              return s;
            }).toList();

            for (String json in jsonStrings) {
              json = json.replaceAll(
                  RegExp(r'[{}"]'), '');
              List<String> pairs = json.split(', ');
              for (String pair in pairs) {
                if (pair.contains('chat_id:')) {
                  jsonMap['chat_id'] =
                      int.tryParse(pair.replaceAll('chat_id: ', ''));
                } else if (pair.contains('chat_title:')) {
                  jsonMap['chat_title'] = pair.replaceAll('chat_title: ', '');
                } else if (pair.contains('ai_message_id:')) {
                  jsonMap['ai_message_id'] =
                      pair.replaceAll('ai_message_id: ', '');
                } else if (pair.contains('human_message_id:')) {
                  jsonMap['human_message_id'] =
                      pair.replaceAll('human_message_id: ', '');
                } else if (pair.contains('credit:')) {
                  jsonMap['credit'] = pair.replaceAll('credit: ', '');
                } else if (pair.contains('free:')) {
                  jsonMap['free'] = pair.replaceAll('free: ', '');
                } else if (pair.contains('gift:')) {
                  jsonMap['gift'] = pair.replaceAll('gift: ', '');
                } else if (pair.contains('human_message_created_at:')) {
                  jsonMap['human_message_created_at'] =
                      pair.replaceAll('human_message_created_at: ', '');
                } else if (pair.contains('ai_message_created_at:')) {
                  jsonMap['ai_message_created_at'] =
                      pair.replaceAll('ai_message_created_at: ', '');
                } else {
                  jsonMap['content'] += pair
                      .replaceAll('content: ', '')
                      .replaceAll('\\n', '\n\n');
                }
              }
            }
          } catch (e) {
            if (kDebugMode) {
              print('Error in Manul Parse: $e');
            }
            jsonMap = {};
          }
        }

        final res = AiResponseModel.fromJson(jsonMap);

        if (res.content != null) {
          result += res.content ?? '';
          if (res.content!.startsWith('http')) {
            if (res.content!.isImage()) {
              emit(ReceiveMessageOnResponsing(text: 'در حال آماده‌سازی تصویر'));
            } else if (res.content!.isAudio()) {
              emit(ReceiveMessageOnResponsing(text: 'در حال آماده‌سازی صوت'));
            } else if (res.content!.isDocument()) {
              emit(ReceiveMessageOnResponsing(text: 'در حال آماده‌سازی فایل'));
            }
          } else {
            emit(ReceiveMessageOnResponsing(text: result));
          }
        }
        aiResponseModel = aiResponseModel.copyWith(
            error: res.error,
            credit: res.credit,
            detail: res.detail,
            statusCode: res.statusCode,
            aiMessageId: res.aiMessageId,
            chatId: res.chatId,
            chatTitle: res.chatTitle,
            content: result.isEmpty ? res.content : result,
            freeCredit: res.freeCredit,
            humanMessageId: res.humanMessageId);
      }
      await scrollToEnd();

      if (aiResponseModel.content != null && 
          aiResponseModel.content!.startsWith('http')) {
        await Future.delayed(const Duration(milliseconds: 500));
      }

      if (aiResponseModel.error ?? true) {
        emit(ReceiveMessageOnFail(
            oldHumanMessageId: request.messageId ?? '',
            detail: 'خطا از سمت سرور لطفا لحظاتی دیگر دوباره تلاش کنید',
            statusCode: aiResponseModel.statusCode ?? 500));
      } else {
        final message = Messages(
            id: aiResponseModel.aiMessageId,
            query: request.query,
            role: 'ai',
            content: [
              if (aiResponseModel.content != null)
                Content(
                    audioUrl: aiResponseModel.content!.isURL() &&
                            aiResponseModel.content!.isAudio()
                        ? FileUrl(url: aiResponseModel.content)
                        : null,
                    pdfUrl: aiResponseModel.content!.isURL() &&
                            aiResponseModel.content!.isDocument()
                        ? FileUrl(url: aiResponseModel.content)
                        : null,
                    type: aiResponseModel.content!.isURL()
                        ? aiResponseModel.content!.isAudio()
                            ? 'audio'
                            : aiResponseModel.content!.isImage()
                                ? 'image'
                                : aiResponseModel.content!.isDocument()
                                    ? 'doc'
                                    : 'text'
                        : 'text',
                    text: aiResponseModel.content!.isURL()
                        ? null
                        : aiResponseModel.content,
                    imageUrl: aiResponseModel.content!.isURL() &&
                            aiResponseModel.content!.isImage()
                        ? FileUrl(url: aiResponseModel.content)
                        : null)
            ]);
        emit(ReceiveMessageDone(
            model: aiResponseModel,
            message: message,
            oldHumanMessageId: request.messageId!));
      }
    } catch (e) {
      // if (e.response?.statusCode == 403) {
      //   emit(const SendMessageError('موجودی شماکافی نمیباشد'));
      // } else {
      //   emit(SendMessageError('Error: $e'));
      // }
      emit(ReceiveMessageOnFail(
          detail: 'خطا از سمت سرور لطفا لحظاتی دیگر دوباره تلاش کنید',
          statusCode: 500,
          oldHumanMessageId: request.messageId ?? ''));
    }
    onResponse.value = false;
    await Future.delayed(const Duration(milliseconds: 300));
    await scrollToEnd();
  }
}
