import 'dart:async';
import 'dart:convert';

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

import 'package:f0ckapp/models/mediaitem_model.dart';
import 'package:f0ckapp/models/suggestion_model.dart';

final FlutterSecureStorage storage = const FlutterSecureStorage(
  aOptions: AndroidOptions(encryptedSharedPreferences: true),
);

Future<List<MediaItem>> fetchMedia({
  int? older,
  String type = 'image',
  int mode = 0,
  bool random = false,
  String? tag,
}) async {
  final Uri url = Uri.parse('https://api.f0ck.me/items/get').replace(
    queryParameters: {
      'type': type,
      'mode': mode.toString(),
      'random': (random ? 1 : 0).toString(),
      if (tag != null) 'tag': tag,
      if (older != null) 'older': older.toString(),
    },
  );

  final http.Response response = await http.get(url);
  if (response.statusCode == 200) {
    final List<dynamic> jsonList = jsonDecode(response.body);
    return jsonList.map((item) => MediaItem.fromJson(item)).toList();
  } else {
    throw Exception('Fehler beim Abrufen der Medien: ${response.statusCode}');
  }
}

Future<MediaItem> fetchMediaDetail(int itemId) async {
  final Uri url = Uri.parse('https://api.f0ck.me/item/${itemId.toString()}');

  final http.Response response = await http.get(url);
  if (response.statusCode == 200) {
    final Map<String, dynamic> jsonResponse = jsonDecode(response.body);

    return MediaItem.fromJson(jsonResponse);
  } else {
    throw Exception(
      'Fehler beim Abrufen der Media-Details: ${response.statusCode}',
    );
  }
}

Future<List<Suggestion>> fetchSuggestions(String query) async {
  final Uri uri = Uri.parse('https://api.f0ck.me/search/?q=$query');
  try {
    final http.Response response = await http
        .get(uri)
        .timeout(const Duration(seconds: 5));

    if (response.statusCode == 200) {
      final dynamic decoded = jsonDecode(response.body);
      if (decoded is List) {
        final suggestions = decoded
            .map((item) => Suggestion.fromJson(item as Map<String, dynamic>))
            .toList();
        suggestions.sort((a, b) => b.score.compareTo(a.score));
        return suggestions;
      } else {
        throw Exception('Unerwartetes Format: Es wurde eine Liste erwartet.');
      }
    } else if (response.statusCode == 400) {
      final dynamic error = jsonDecode(response.body);
      final String message = error is Map<String, dynamic>
          ? error['detail']?.toString() ?? 'Unbekannter Fehler.'
          : 'Unbekannter Fehler.';
      throw Exception('Client-Fehler 400: $message');
    } else {
      throw Exception(
        'Fehler beim Abrufen der Vorschläge: ${response.statusCode}',
      );
    }
  } on TimeoutException {
    throw Exception('Anfrage an die API hat zu lange gedauert.');
  } catch (e) {
    throw Exception('Fehler bei der Verarbeitung der Anfrage: $e');
  }
}

Future<bool> login(String username, String password) async {
  final Uri url = Uri.parse('https://api.f0ck.me/login');

  final http.Response response = await http.post(
    url,
    body: {'username': username, 'password': password},
  );

  if (response.statusCode == 200) {
    final dynamic data = jsonDecode(response.body);
    final token = data['token'];
    if (token != null) {
      await storage.write(key: "token", value: token);
      return true;
    } else {
      throw Exception('Token nicht im Response enthalten.');
    }
  } else {
    throw Exception('Login fehlgeschlagen: ${response.statusCode}');
  }
}
