import 'package:jwt_decoder/jwt_decoder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:chepuhagram/core/constants.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class ApiService extends ChangeNotifier {
  final _client = http.Client();
  final _storage = const FlutterSecureStorage();

  Future<String?> uploadMedia(List<int> bytes) async {
    try {
      final token = getAccessToken();
      var request = http.MultipartRequest(
        'POST',
        Uri.parse('${AppConstants.baseUrl}/media/upload'),
      );
      request.headers.addAll({
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      });
      // Добавляем файл в запрос
      request.files.add(
        http.MultipartFile.fromBytes(
          'file',
          bytes,
          filename: 'media.enc', // Имя файла для сервера
        ),
      );

      // Добавь заголовки авторизации, если они у тебя есть (JWT и т.д.)
      // request.headers.addAll({'Authorization': 'Bearer $token'});

      var streamedResponse = await request.send();
      var response = await http.Response.fromStream(streamedResponse);

      if (response.statusCode == 200) {
        // Предполагаем, что сервер возвращает JSON {"file_id": "..."}
        final data = jsonDecode(response.body);
        return data['file_id'];
      }
      return null;
    } catch (e) {
      print("Ошибка API при загрузке: $e");
      return null;
    }
  }

  Future<bool> refreshToken() async {
    notifyListeners();

    try {
      final refreshToken = await _storage.read(key: 'refresh_token');
      final response = await _client.post(
        Uri.parse('${AppConstants.baseUrl}/auth/refresh'),
        body: jsonEncode({'refresh_token': refreshToken}),
        headers: {'Content-Type': 'application/json'},
      );

      final decodedResponse =
          jsonDecode(utf8.decode(response.bodyBytes)) as Map;

      if (response.statusCode == 200) {
        await _storage.write(
          key: 'access_token',
          value: decodedResponse['access_token'],
        );
        await _storage.write(
          key: 'refresh_token',
          value: decodedResponse['refresh_token'],
        );
        notifyListeners();
        return true;
      } else {
        notifyListeners();
        return false;
      }
    } catch (e) {
      notifyListeners();
      rethrow;
    }
  }

  Future<String?> getAccessToken() async {
    String? token = await _storage.read(key: 'access_token');

    if (token != null) {
      bool isExpiredSoon =
          JwtDecoder.isExpired(token) ||
          JwtDecoder.getRemainingTime(token).inMinutes < 2;

      if (isExpiredSoon) {
        bool refreshed = await refreshToken();
        if (refreshed) {
          token = await _storage.read(key: 'access_token');
        } else {
          return null;
        }
      }
    }
    return token;
  }

  Future<bool> updateFcmToken(String fcmtoken) async {
    notifyListeners();

    try {
      final token = await getAccessToken();
      final response = await _client.post(
        Uri.parse('${AppConstants.baseUrl}/auth/update-fcm?token=$fcmtoken'),
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $token',
        },
      );

      if (response.statusCode == 200) {
        return true;
      } else {
        print("Ошибка установки ключа: ${response.statusCode}");
        return false;
      }
    } catch (e) {
      rethrow;
    } finally {
      notifyListeners();
    }
  }

  Future<bool> setPublicKey(String publicKey) async {
    notifyListeners();

    try {
      final token = await getAccessToken();
      final response = await _client.post(
        Uri.parse('${AppConstants.baseUrl}/auth/set-public-key'),
        body: jsonEncode({'public_key': publicKey}),
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $token',
        },
      );

      if (response.statusCode == 200) {
        return true;
      } else {
        print("Ошибка установки ключа: ${response.statusCode}");
        return false;
      }
    } catch (e) {
      rethrow;
    } finally {
      notifyListeners();
    }
  }

  Future<Map<String, dynamic>> getMe() async {
    final token = await getAccessToken();
    final response = await _client.get(
      Uri.parse('${AppConstants.baseUrl}/users/me'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );

    if (response.statusCode == 200) {
      return jsonDecode(utf8.decode(response.bodyBytes))
          as Map<String, dynamic>;
    }
    throw Exception('Не удалось получить данные пользователя');
  }

  Future<bool> updateEncryptedPrivateKey(String encryptedPrivateKey) async {
    final token = await getAccessToken();
    final response = await _client.put(
      Uri.parse('${AppConstants.baseUrl}/users/me/encryption-key'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({'encrypted_private_key': encryptedPrivateKey}),
    );

    return response.statusCode == 200;
  }

  Future<bool> changePassword(
    String currentPassword,
    String newPassword,
  ) async {
    final token = await getAccessToken();
    final response = await _client.put(
      Uri.parse('${AppConstants.baseUrl}/users/me/password'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({
        'current_password': currentPassword,
        'new_password': newPassword,
      }),
    );

    return response.statusCode == 200;
  }

  Future<List<dynamic>> getChatHistory(int contactId) async {
    final token = await getAccessToken();
    final response = await _client.get(
      Uri.parse(
        '${AppConstants.baseUrl}/messages/history/${contactId.toString()}',
      ),
      headers: {
        'Content-Type': 'application/json',
        "Authorization": "Bearer $token",
      },
    );
    return jsonDecode(response.body) as List<dynamic>;
  }

  Future<Map<String, dynamic>> updateMe({
    required String username,
    required String firstName,
    required String lastName,
    String? phone,
    String? email,
    String? about,
  }) async {
    final token = await getAccessToken();
    final response = await _client.put(
      Uri.parse('${AppConstants.baseUrl}/users/me'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({
        'username': username,
        'first_name': firstName,
        'last_name': lastName,
        'phone': (phone == null || phone.trim().isEmpty) ? null : phone.trim(),
        'email': (email == null || email.trim().isEmpty) ? null : email.trim(),
        'about': (about == null || about.trim().isEmpty) ? null : about.trim(),
      }),
    );

    final decoded = jsonDecode(utf8.decode(response.bodyBytes));
    if (response.statusCode == 200) {
      return decoded as Map<String, dynamic>;
    }
    throw Exception(
      (decoded is Map && decoded['detail'] != null)
          ? decoded['detail']
          : 'Failed to update profile',
    );
  }

  Future<Map<String, dynamic>> getUserById(int userId) async {
    final token = await getAccessToken();
    final response = await _client.get(
      Uri.parse('${AppConstants.baseUrl}/users/$userId'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );

    if (response.statusCode == 200) {
      return jsonDecode(utf8.decode(response.bodyBytes))
          as Map<String, dynamic>;
    }
    throw Exception('Не удалось получить информацию о пользователе');
  }

  Future<bool> updatePrivacySettings({
    bool? showEmail,
    bool? showPhone,
    bool? showAvatar,
    bool? showAbout,
    bool? showUsername,
    bool? showLastOnline,
  }) async {
    final token = await getAccessToken();
    final response = await _client.put(
      Uri.parse('${AppConstants.baseUrl}/users/me/privacy'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({
        if (showEmail != null) 'show_email': showEmail,
        if (showPhone != null) 'show_phone': showPhone,
        if (showAvatar != null) 'show_avatar': showAvatar,
        if (showAbout != null) 'show_about': showAbout,
        if (showUsername != null) 'show_username': showUsername,
        if (showLastOnline != null) 'show_last_online': showLastOnline,
      }),
    );

    return response.statusCode == 200;
  }

  Future<Map<String, dynamic>> getPrivacySettings() async {
    final token = await getAccessToken();
    final response = await _client.get(
      Uri.parse('${AppConstants.baseUrl}/users/me/privacy'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );

    if (response.statusCode == 200) {
      return jsonDecode(utf8.decode(response.bodyBytes))
          as Map<String, dynamic>;
    }
    throw Exception('Не удалось получить настройки конфиденциальности');
  }

  Future<bool> updateAvatar(String fileId) async {
    final token = await getAccessToken();
    final response = await _client.put(
      Uri.parse('${AppConstants.baseUrl}/users/me/avatar'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({'avatar_file_id': fileId}),
    );
    return response.statusCode == 200;
  }

  Future<Map<String, dynamic>> enableTotp() async {
    final token = await getAccessToken();
    final response = await _client.post(
      Uri.parse('${AppConstants.baseUrl}/auth/totp/enable'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );

    if (response.statusCode == 200) {
      return jsonDecode(utf8.decode(response.bodyBytes))
          as Map<String, dynamic>;
    }
    throw Exception(
      (jsonDecode(response.body) as Map<String, dynamic>)['detail'] ??
          'Failed to enable TOTP',
    );
  }

  Future<bool> verifyTotp(String code) async {
    final token = await getAccessToken();
    final response = await _client.post(
      Uri.parse('${AppConstants.baseUrl}/auth/totp/verify'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({'code': code}),
    );
    return response.statusCode == 200;
  }

  Future<bool> disableTotp() async {
    final token = await getAccessToken();
    final response = await _client.post(
      Uri.parse('${AppConstants.baseUrl}/auth/totp/disable'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );
    return response.statusCode == 200;
  }

  Future<bool> deleteAllMessages() async {
    final token = await getAccessToken();
    final response = await _client.delete(
      Uri.parse('${AppConstants.baseUrl}/messages/all'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );
    return response.statusCode == 200;
  }
}
