import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:path/path.dart' as path;
import 'package:environment_monitoring_app/auth_provider.dart';

class BaseApiService {
  final String _baseUrl = 'https://dev14.pstw.com.my/v1';

  // Private helper to construct headers with the auth token
  Future<Map<String, String>> _getHeaders() async {
    final prefs = await SharedPreferences.getInstance();
    final String? token = prefs.getString(AuthProvider.tokenKey);
    // For multipart requests, 'Content-Type' is set by the http client.
    // We only need Authorization here.
    return {
      if (token != null) 'Authorization': 'Bearer $token',
    };
  }

  // Private helper for JSON headers
  Future<Map<String, String>> _getJsonHeaders() async {
    final headers = await _getHeaders();
    headers['Content-Type'] = 'application/json';
    return headers;
  }

  // Generic GET request handler
  Future<Map<String, dynamic>> get(String endpoint) async {
    final url = Uri.parse('$_baseUrl/$endpoint');
    try {
      final response = await http.get(url, headers: await _getJsonHeaders());
      return _handleResponse(response);
    } catch (e) {
      debugPrint('GET request failed: $e');
      return {'success': false, 'message': 'Network error: $e'};
    }
  }

  // Generic POST request handler for JSON data
  Future<Map<String, dynamic>> post(String endpoint, Map<String, dynamic> body) async {
    final url = Uri.parse('$_baseUrl/$endpoint');
    try {
      final response = await http.post(
        url,
        headers: await _getJsonHeaders(),
        body: jsonEncode(body),
      );
      return _handleResponse(response);
    } catch (e) {
      debugPrint('POST request failed: $e');
      return {'success': false, 'message': 'Network error: $e'};
    }
  }

  // Generic handler for multipart (file upload) requests
  Future<Map<String, dynamic>> postMultipart({
    required String endpoint,
    required Map<String, String> fields,
    required Map<String, File> files,
  }) async {
    final url = Uri.parse('$_baseUrl/$endpoint');
    debugPrint('Starting multipart upload to: $url');

    try {
      var request = http.MultipartRequest('POST', url);

      // Get and add headers (Authorization token)
      final headers = await _getHeaders();
      request.headers.addAll(headers);
      debugPrint('Headers added to multipart request.');

      // --- CORRECTED ---
      // This adds each field directly to the request body, which is the standard
      // for multipart/form-data and matches what the PHP backend expects.
      if (fields.isNotEmpty) {
        request.fields.addAll(fields);
        debugPrint('Fields added directly to multipart request: $fields');
      }

      // Add files
      for (var entry in files.entries) {
        debugPrint('Adding file: ${entry.key}, path: ${entry.value.path}');
        request.files.add(await http.MultipartFile.fromPath(
          entry.key,
          entry.value.path,
          filename: path.basename(entry.value.path),
        ));
      }
      debugPrint('${files.length} files added to the request.');

      debugPrint('Sending multipart request...');
      var streamedResponse = await request.send();
      debugPrint('Received response with status code: ${streamedResponse.statusCode}');

      final responseBody = await streamedResponse.stream.bytesToString();
      // We create a standard http.Response to use our standard handler
      return _handleResponse(http.Response(responseBody, streamedResponse.statusCode));

    } catch (e, s) { // Catching both Exception and Error (e.g., OutOfMemoryError)
      debugPrint('FATAL: An error occurred during multipart upload: $e');
      debugPrint('Stack trace: $s');
      return {
        'success': false,
        'message': 'Upload failed due to a critical error. This might be caused by low device memory or a network issue.'
      };
    }
  }

  // Centralized response handling
  Map<String, dynamic> _handleResponse(http.Response response) {
    debugPrint('Handling response. Status: ${response.statusCode}, Body: ${response.body}');
    try {
      final Map<String, dynamic> responseData = jsonDecode(response.body);
      if (response.statusCode >= 200 && response.statusCode < 300) {
        // Assuming the API returns a 'status' field in the JSON body
        if (responseData['status'] == 'success' || responseData['success'] == true) {
          return {'success': true, 'data': responseData['data'], 'message': responseData['message']};
        } else {
          return {'success': false, 'message': responseData['message'] ?? 'An unknown API error occurred.'};
        }
      } else {
        // Handle server errors (4xx, 5xx)
        return {'success': false, 'message': responseData['message'] ?? 'Server error: ${response.statusCode}'};
      }
    } catch (e) {
      // Handle cases where the response body is not valid JSON
      debugPrint('Failed to parse server response: $e');
      return {'success': false, 'message': 'Failed to parse server response. Body: ${response.body}'};
    }
  }
}
