import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:hoshan/data/storage/shared_preferences_helper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

class DioService {
  static String baseURL = 'https://basa.houshan.ai';
  //user
  static String sendOTP = '/v2/user/otp'; //POST
  // static String register = '/user/register'; //POST
  static String loginWithPassword = '/user/login'; //POST
  static String loginWithOTP = '/user/login/otp'; //POST
  static String getInfo = '/user/info'; //GET
  static String editUsername = '/user/username'; //PUT
  static String checkUsername = '/user/username'; //POST
  static String editProfile = '/user/profile'; //PUT
  static String editPassword = '/user/password'; //PUT
  static String deleteProfile = '/user/profile'; //DELETE
  static String giftCode = '/user/code'; //POST
  static String cardNumber = '/user/card-number'; //PUT
  static String addSubUser = '/user/sub-user'; //POST
  static String getSubUsers = '/user/sub-user'; //GET
  static String deleteSubUser(String id) => '/user/sub-user/$id'; //DELETE
  static String reportDay = '/user/report/daily'; //GET
  static String reportWeek = '/user/report/weekly'; //GET
  static String reportPeriodic = '/user/report/periodic'; //GET
  static String reportPiCoin = '/user/report/coin'; //GET
  static String readAllNotifications = '/user/notification'; //PUT
  static String fCMtoken = '/user/firebase-token'; //PUT
  //chatbot
  static String sendMessage = '/chatbot/'; //POST //GET //DELETE //STREAM
  static String chatHistory({required final int id}) =>
      '/chatbot/$id'; //GET //DELETE q{id}
  static String editTitle({required final int id}) =>
      '/chatbot/$id/title'; //PUT
  static String archive({required final int id}) =>
      '/chatbot/$id/archive'; //PUT
  static String relatedQuestions({required final int id}) =>
      '/chatbot/$id/related_questions'; //POST q{id};
  static String messageDelete(
          {required final int id, required final String messageId}) =>
      '/chatbot/$id/message/$messageId'; //DELETE q{id} q{message_id}
  static String likeMessage(
          {required final int id, required final String messageId}) =>
      '/chatbot/$id/message/$messageId/feedback'; //PUT q{id} q{message_id}
  //bot
  static String getAllBots = '/bot/'; //GET q{string:serach}
  static String getSingleBot(int id) => '/bot/$id'; //GET q{string:serach}
  //category
  static String sendMessageTool({required final int id}) =>
      '/tool/$id'; //POST //GET //DELETE //STREAM
  static String allCategories = '/category/'; //GET
  static String toolsCategories = '/v2/category/tool'; //GET
  //suno
  static String sunoTask({required final String taskId}) =>
      '/api/suno/tasks/$taskId'; //GET
  //Ticket
  static String ticket = '/ticket/'; //GET
  static String deleteTicket(int id) => '/ticket/$id'; //GET
  //Forum
  static String forumComments = '/forum/comment/'; //GET //POST
  static String forumReplieComments(int id) => '/forum/comment/$id'; //GET
  static String forumCommentsFeedback(int id) =>
      '/forum/comment/$id/feedback'; //PUT
  //Assistant
  static String getGlobalAssistants = '/bot/assistant'; //GET
  static String getPersonalAssistants = '/bot/personal'; //GET
  static String getPersonalAssistant(int id) => '/bot/personal/$id'; //GET
  static String getGlobalAssistant(int id) => '/bot/$id'; //GET
  static String getAssistantComments(int id) => '/bot/$id/comment'; //GET
  static String markedBot(int id) => '/bot/$id/mark'; //PUT
  //paymant
  static String paymant = '/paymant/'; //GET
  static String paymantBazar = '/paymant/bazzar'; //GET
  static String paymantMyket = '/paymant/myket'; //GET
  static String paymantHistory = '/paymant/history'; //GET
  static String paymantPlans = '/v2/paymant/plan'; //GET
  static String discount = '/discount/'; //POST
  static String settlement = '/paymant/settlement'; //POST
  static String homeBanner = '/banner/'; //GET
  //generators
  static String media = '/category/media'; //GET
  static String effects = '/category/effect'; //GET
  static String singleMedia(int id) => '/category/media/$id'; //GET
  //characters
  static String characters = '/category/character'; //GET
  //events
  static String events = '/event/';
  static String remaining = '/advertisement/remaining';
  DioService() {
    if (kDebugMode) {
      String token = AuthTokenStorage.getToken();
      print("AuthToken: $token");
    }
  }
  static const _canLog = kDebugMode && !kIsWeb;

  static final Dio _dio = Dio(BaseOptions(
      baseUrl: baseURL,
      connectTimeout: const Duration(minutes: 1),
      responseType: ResponseType.json,
      headers: {
        "Content-Type": "application/json",
        'accept': '*/*',
        // 'Authorization': "Bearer $token",
      }))
    ..interceptors.add(PrettyDioLogger(enabled: _canLog));

  static final Dio _dioStream = Dio(BaseOptions(
      baseUrl: baseURL,
      connectTimeout: const Duration(minutes: 10),
      receiveTimeout: const Duration(minutes: 10),
      sendTimeout: const Duration(minutes: 10),
      responseType: ResponseType.stream,
      headers: {
        "Content-Type": "application/json",
        'accept': '*/*',
      }))
    ..interceptors.add(PrettyDioLogger(
        enabled: _canLog,
        requestBody: true,
        responseBody: false // غیرفعال کردن لاگ body برای stream
        ));

  Dio sendRequest() {
    String token = AuthTokenStorage.getToken();
    _dio.options.headers.addAll({'Authorization': "Bearer $token"});
    return _dio;
  }

  Dio sendRequestStream() {
    String token = AuthTokenStorage.getToken();
    _dioStream.options.headers.addAll({'Authorization': "Bearer $token"});
    return _dioStream;
  }

  static final Map<String, Future<XFile?>> _ongoingDownloads = {};

  static Future<XFile?> downloadFile(String url,
      {String? cDirectory, Function(int, int)? onReceiveProgress}) async {
    if (_ongoingDownloads.containsKey(url)) {
      return _ongoingDownloads[url];
    }

    final downloadFuture = _downloadFile(url,
        cDirectory: cDirectory, onReceiveProgress: onReceiveProgress);
    _ongoingDownloads[url] = downloadFuture;

    final result = await downloadFuture;
    _ongoingDownloads.remove(url);
    return result;
  }

  static Future<XFile?> _downloadFile(String url,
      {String? cDirectory, Function(int, int)? onReceiveProgress}) async {
    try {
      final response = await _dio.get(url,
          options: Options(responseType: ResponseType.bytes),
          onReceiveProgress: onReceiveProgress);
      if (response.statusCode == 200) {
        final blob = response.data;
        final fileName = url.split('/').last;
        if (cDirectory != null) {
          final filePath = '$cDirectory/$fileName';
          final file = File(filePath);
          await file.writeAsBytes(blob);
          return XFile(filePath);
        } else {
          final directory = await getApplicationDocumentsDirectory();
          final filePath = '${directory.path}/$fileName';
          final file = File(filePath);
          await file.writeAsBytes(blob);
          return XFile(filePath);
        }
      } else {
        debugPrint(
            "Error: Unable to download file. Status: ${response.statusCode}");
        return null;
      }
    } on DioException catch (e) {
      if (kDebugMode) {
        print("Error downloading file: $e");
      }
      return null;
    }
  }

  static Future<MultipartFile> getMultipartFile(XFile file) async {
    if (kIsWeb) {
      final bytes = await file.readAsBytes();
      return MultipartFile.fromBytes(bytes, filename: file.name);
    } else {
      return MultipartFile.fromFile(file.path, filename: file.name);
    }
  }

  static Future<int?> getFileSize(String url) async {
    try {
      Dio dio = Dio();
      Response response =
          await dio.head(url, options: Options(followRedirects: true));

      String? contentLength = response.headers.value('content-length');
      return contentLength != null ? int.parse(contentLength) : null;
    } catch (e) {
      if (kDebugMode) {
        print("Error: $e");
      }
      return null;
    }
  }
}
