import 'dart:convert';

import 'package:shared_preferences/shared_preferences.dart';

import '../network/api_client.dart';

class OfflineRequest {
  final String method;
  final String path;
  final Map<String, dynamic> body;
  final DateTime createdAt;

  OfflineRequest({
    required this.method,
    required this.path,
    required this.body,
    required this.createdAt,
  });

  Map<String, dynamic> toJson() => {
        'method': method,
        'path': path,
        'body': body,
        'createdAt': createdAt.toIso8601String(),
      };

  factory OfflineRequest.fromJson(Map<String, dynamic> json) => OfflineRequest(
        method: json['method'] as String,
        path: json['path'] as String,
        body: Map<String, dynamic>.from(json['body'] as Map),
        createdAt: DateTime.parse(json['createdAt'] as String),
      );
}

class OfflineQueueService {
  static const _key = 'offline_request_queue';

  Future<void> enqueue(OfflineRequest request) async {
    final prefs = await SharedPreferences.getInstance();
    final queue = await readAll();
    queue.add(request);
    await prefs.setString(_key, jsonEncode(queue.map((e) => e.toJson()).toList()));
  }

  Future<List<OfflineRequest>> readAll() async {
    final prefs = await SharedPreferences.getInstance();
    final raw = prefs.getString(_key);
    if (raw == null || raw.isEmpty) return [];
    final decoded = jsonDecode(raw) as List<dynamic>;
    return decoded.map((e) => OfflineRequest.fromJson(Map<String, dynamic>.from(e as Map))).toList();
  }

  Future<void> clear() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(_key);
  }

  Future<int> syncPending(ApiClient apiClient) async {
    final queue = await readAll();
    if (queue.isEmpty) return 0;

    final remaining = <OfflineRequest>[];
    var synced = 0;
    for (final request in queue) {
      try {
        switch (request.method.toUpperCase()) {
          case 'POST':
            await apiClient.dio.post(request.path, data: request.body);
            break;
          case 'PUT':
            await apiClient.dio.put(request.path, data: request.body);
            break;
          default:
            await apiClient.dio.get(request.path);
        }
        synced++;
      } catch (_) {
        remaining.add(request);
      }
    }

    final prefs = await SharedPreferences.getInstance();
    if (remaining.isEmpty) {
      await prefs.remove(_key);
    } else {
      await prefs.setString(_key, jsonEncode(remaining.map((e) => e.toJson()).toList()));
    }
    return synced;
  }
}
