// lib/services/api_service.dart

import 'dart:io';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';

import 'package:environment_monitoring_app/services/base_api_service.dart';
import 'package:environment_monitoring_app/services/telegram_service.dart';
import 'package:environment_monitoring_app/services/server_config_service.dart';

// Import the new separated files
import 'package:environment_monitoring_app/services/database_helper.dart';
import 'package:environment_monitoring_app/services/marine_api_service.dart';
import 'package:environment_monitoring_app/services/river_api_service.dart';
import 'package:environment_monitoring_app/services/air_api_service.dart';

// Removed: Models that are no longer directly used by this top-level class
// import 'package:environment_monitoring_app/models/air_collection_data.dart';
// import 'package:environment_monitoring_app/models/air_installation_data.dart';
// import 'package:environment_monitoring_app/models/marine_manual_pre_departure_checklist_data.dart';
// import 'package:environment_monitoring_app/models/marine_manual_sonde_calibration_data.dart';
// import 'package:environment_monitoring_app/models/marine_manual_equipment_maintenance_data.dart';

// =======================================================================
// Part 1: Unified API Service
// =======================================================================

class ApiService {
  final BaseApiService _baseService = BaseApiService();
  final DatabaseHelper dbHelper = DatabaseHelper();
  final ServerConfigService _serverConfigService = ServerConfigService();

  late final MarineApiService marine;
  late final RiverApiService river;
  late final AirApiService air;

  static const String imageBaseUrl = 'https://mms-apiv4.pstw.com.my/';

  ApiService({required TelegramService telegramService}) {
    // --- MODIFIED CONSTRUCTOR ---
    // Note that marine and river no longer take dbHelper, matching your new files
    marine = MarineApiService(_baseService, telegramService, _serverConfigService);
    river = RiverApiService(_baseService, telegramService, _serverConfigService);
    // AirApiService also doesn't need the dbHelper
    air = AirApiService(_baseService, telegramService, _serverConfigService);
  }

  // --- Core API Methods ---
  Future<Map<String, dynamic>> login(String email, String password) async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.post(baseUrl, 'auth/login', {'email': email, 'password': password});
  }

  Future<Map<String, dynamic>> register({
    required String username,
    String? firstName,
    String? lastName,
    required String email,
    required String password,
    String? phoneNumber,
    int? departmentId,
    int? companyId,
    int? positionId,
  }) async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    final Map<String, dynamic> body = {
      'username': username,
      'email': email,
      'password': password,
      'first_name': firstName ?? '',
      'last_name': lastName ?? '',
      'phone_number': phoneNumber ?? '',
      'department_id': departmentId,
      'company_id': companyId,
      'position_id': positionId,
    };
    body.removeWhere((key, value) => value == null);
    return _baseService.post(baseUrl, 'auth/register', body);
  }

  Future<Map<String, dynamic>> post(String endpoint, Map<String, dynamic> data) async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.post(baseUrl, endpoint, data);
  }

  Future<Map<String, dynamic>> getProfile() async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.get(baseUrl, 'profile');
  }

  Future<Map<String, dynamic>> getAllUsers() async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.get(baseUrl, 'users');
  }

  Future<Map<String, dynamic>> getAllDepartments() async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.get(baseUrl, 'departments');
  }

  Future<Map<String, dynamic>> getAllCompanies() async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.get(baseUrl, 'companies');
  }

  Future<Map<String, dynamic>> getAllPositions() async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.get(baseUrl, 'positions');
  }

  Future<Map<String, dynamic>> getAllStates() async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.get(baseUrl, 'states');
  }

  Future<Map<String, dynamic>> sendTelegramAlert({
    required String chatId,
    required String message,
  }) async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.post(baseUrl, 'marine/telegram-alert', { // Note: Endpoint might need generalization if used by other modules
      'chat_id': chatId,
      'message': message,
    });
  }

  Future<File?> downloadProfilePicture(String imageUrl, String localPath) async {
    try {
      final response = await http.get(Uri.parse(imageUrl));
      if (response.statusCode == 200) {
        final File file = File(localPath);
        await file.parent.create(recursive: true);
        await file.writeAsBytes(response.bodyBytes);
        return file;
      }
    } catch (e) {
      debugPrint('Error downloading profile picture: $e');
    }
    return null;
  }

  Future<Map<String, dynamic>> uploadProfilePicture(File imageFile) async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    return _baseService.postMultipart(
        baseUrl: baseUrl,
        endpoint: 'profile/upload-picture',
        fields: {},
        files: {'profile_picture': imageFile});
  }

  // --- ADDED THIS NEW METHOD ---
  /// Uploads the user's signature as a transparent PNG file.
  Future<Map<String, dynamic>> uploadSignature(File imageFile) async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    // We assume the endpoint is 'profile/upload-signature'
    // and the server expects the file field name to be 'signature'.
    return _baseService.postMultipart(
        baseUrl: baseUrl,
        endpoint: 'profile/upload-signature',
        fields: {},
        files: {'signature': imageFile});
  }
  // --- END OF NEW METHOD ---

  Future<Map<String, dynamic>> refreshProfile() async {
    debugPrint('ApiService: Refreshing profile data from server...');
    final result = await getProfile();
    if (result['success'] == true && result['data'] != null) {
      await dbHelper.saveProfile(result['data']);
      debugPrint('ApiService: Profile data refreshed and saved to local DB.');
    }
    return result;
  }

  Future<void> validateToken() async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    await _baseService.get(baseUrl, 'profile');
  }

  // --- NEW METHOD FOR FIRST TIME LOGIN ---
  /// Fetches critical configuration data (API and FTP settings) needed for
  /// immediate operation. This should be called during the login/splash sequence.
  Future<void> fetchInitialConfigurations() async {
    debugPrint("ApiService: Fetching initial API and FTP configurations...");
    final baseUrl = await _serverConfigService.getActiveApiUrl();

    try {
      // 1. Fetch API Configs
      final apiResult = await _baseService.get(baseUrl, 'api-configs');
      if (apiResult['success'] == true && apiResult['data'] != null) {
        final apiData = List<Map<String, dynamic>>.from(apiResult['data']['updated'] ?? []);
        await dbHelper.upsertApiConfigs(apiData);
        debugPrint("Initial API Configs synced: ${apiData.length} items.");
      }

      // 2. Fetch FTP Configs
      final ftpResult = await _baseService.get(baseUrl, 'ftp-configs');
      if (ftpResult['success'] == true && ftpResult['data'] != null) {
        final ftpData = List<Map<String, dynamic>>.from(ftpResult['data']['updated'] ?? []);
        await dbHelper.upsertFtpConfigs(ftpData);
        debugPrint("Initial FTP Configs synced: ${ftpData.length} items.");
      }
    } catch (e) {
      debugPrint("ApiService: Error fetching initial configurations: $e");
      // We don't rethrow here to allow login to proceed, but UserPreferencesService
      // will handle the missing data gracefully (by not saving defaults yet).
    }
  }

  Future<Map<String, dynamic>> _fetchDelta(String endpoint, String? lastSyncTimestamp) async {
    final baseUrl = await _serverConfigService.getActiveApiUrl();
    String url = endpoint;
    if (lastSyncTimestamp != null) {
      url += '?since=$lastSyncTimestamp';
    }
    return _baseService.get(baseUrl, url);
  }

  Future<Map<String, dynamic>> syncAllData({String? lastSyncTimestamp}) async {
    debugPrint('ApiService: Starting DELTA data sync. Since: $lastSyncTimestamp');
    try {
      final syncTasks = {
        'profile': {
          'endpoint': 'profile',
          'handler': (d, id) async {
            if (d.isNotEmpty) await dbHelper.saveProfile(d.first);
          }
        },
        'allUsers': {
          'endpoint': 'users',
          'handler': (d, id) async {
            await dbHelper.upsertUsers(d);
            await dbHelper.deleteUsers(id);
          }
        },
        'documents': {
          'endpoint': 'documents',
          'handler': (d, id) async {
            await dbHelper.upsertDocuments(d);
            await dbHelper.deleteDocuments(id);
          }
        },
        'tarballStations': {
          'endpoint': 'marine/tarball/stations',
          'handler': (d, id) async {
            await dbHelper.upsertTarballStations(d);
            await dbHelper.deleteTarballStations(id);
          }
        },
        'manualStations': {
          'endpoint': 'marine/manual/stations',
          'handler': (d, id) async {
            await dbHelper.upsertManualStations(d);
            await dbHelper.deleteManualStations(id);
          }
        },
        'tarballClassifications': {
          'endpoint': 'marine/tarball/classifications',
          'handler': (d, id) async {
            await dbHelper.upsertTarballClassifications(d);
            await dbHelper.deleteTarballClassifications(id);
          }
        },
        'riverManualStations': {
          'endpoint': 'river/manual-stations',
          'handler': (d, id) async {
            await dbHelper.upsertRiverManualStations(d);
            await dbHelper.deleteRiverManualStations(id);
          }
        },
        'riverTriennialStations': {
          'endpoint': 'river/triennial-stations',
          'handler': (d, id) async {
            await dbHelper.upsertRiverTriennialStations(d);
            await dbHelper.deleteRiverTriennialStations(id);
          }
        },
        // --- REMOVED: River Investigative Stations Sync ---
        // The 'riverInvestigativeStations' task has been removed
        // as per the request to use river manual stations instead.
        // --- END REMOVED ---
        'departments': {
          'endpoint': 'departments',
          'handler': (d, id) async {
            await dbHelper.upsertDepartments(d);
            await dbHelper.deleteDepartments(id);
          }
        },
        'companies': {
          'endpoint': 'companies',
          'handler': (d, id) async {
            await dbHelper.upsertCompanies(d);
            await dbHelper.deleteCompanies(id);
          }
        },
        'positions': {
          'endpoint': 'positions',
          'handler': (d, id) async {
            await dbHelper.upsertPositions(d);
            await dbHelper.deletePositions(id);
          }
        },
        'airManualStations': {
          'endpoint': 'air/manual-stations',
          'handler': (d, id) async {
            await dbHelper.upsertAirManualStations(d);
            await dbHelper.deleteAirManualStations(id);
          }
        },
        'airClients': {
          'endpoint': 'air/clients',
          'handler': (d, id) async {
            await dbHelper.upsertAirClients(d);
            await dbHelper.deleteAirClients(id);
          }
        },
        'states': {
          'endpoint': 'states',
          'handler': (d, id) async {
            await dbHelper.upsertStates(d);
            await dbHelper.deleteStates(id);
          }
        },
        'appSettings': {
          'endpoint': 'settings',
          'handler': (d, id) async {
            await dbHelper.upsertAppSettings(d);
            await dbHelper.deleteAppSettings(id);
          }
        },
        'npeParameterLimits': {
          'endpoint': 'npe-parameter-limits',
          'handler': (d, id) async {
            await dbHelper.upsertNpeParameterLimits(d);
            await dbHelper.deleteNpeParameterLimits(id);
          }
        },
        'marineParameterLimits': {
          'endpoint': 'marine-parameter-limits',
          'handler': (d, id) async {
            await dbHelper.upsertMarineParameterLimits(d);
            await dbHelper.deleteMarineParameterLimits(id);
          }
        },
        'riverParameterLimits': {
          'endpoint': 'river-parameter-limits',
          'handler': (d, id) async {
            await dbHelper.upsertRiverParameterLimits(d);
            await dbHelper.deleteRiverParameterLimits(id);
          }
        },
        'apiConfigs': {
          'endpoint': 'api-configs',
          'handler': (d, id) async {
            await dbHelper.upsertApiConfigs(d);
            await dbHelper.deleteApiConfigs(id);
          }
        },
        'ftpConfigs': {
          'endpoint': 'ftp-configs',
          'handler': (d, id) async {
            await dbHelper.upsertFtpConfigs(d);
            await dbHelper.deleteFtpConfigs(id);
          }
        },
      };

      // Fetch all deltas in parallel
      final fetchFutures = syncTasks.map((key, value) =>
          MapEntry(key, _fetchDelta(value['endpoint'] as String, lastSyncTimestamp)));
      final results = await Future.wait(fetchFutures.values);
      final resultData = Map.fromIterables(fetchFutures.keys, results);

      // Process and save all changes
      for (var entry in resultData.entries) {
        final key = entry.key;
        final result = entry.value;

        if (result['success'] == true && result['data'] != null) {
          if (key == 'profile') {
            // Handle potential non-list response for profile
            final profileData = result['data'];
            if (profileData is Map<String, dynamic>) {
              await (syncTasks[key]!['handler'] as Function)([profileData], []);
            } else if (profileData is List && profileData.isNotEmpty) {
              await (syncTasks[key]!['handler'] as Function)([profileData.first], []);
            }
          } else {
            // --- REVERTED TO ORIGINAL ---
            // The special logic to handle List vs Map is no longer needed
            // since the endpoint causing the problem is no longer being called.
            final updated = List<Map<String, dynamic>>.from(result['data']['updated'] ?? []);
            final deleted = List<dynamic>.from(result['data']['deleted'] ?? []);
            await (syncTasks[key]!['handler'] as Function)(updated, deleted);
            // --- END REVERTED ---
          }
        } else {
          debugPrint('ApiService: Failed to sync $key. Message: ${result['message']}');
        }
      }

      debugPrint('ApiService: Delta sync complete.');
      return {'success': true, 'message': 'Delta sync successful.'};
    } catch (e) {
      debugPrint('ApiService: Delta data sync failed: $e');
      rethrow;
    }
  }

  Future<Map<String, dynamic>> syncRegistrationData() async {
    debugPrint('ApiService: Starting registration data sync...');
    try {
      final syncTasks = {
        'departments': {
          'endpoint': 'departments',
          'handler': (d, id) async {
            await dbHelper.upsertDepartments(d);
            await dbHelper.deleteDepartments(id);
          }
        },
        'companies': {
          'endpoint': 'companies',
          'handler': (d, id) async {
            await dbHelper.upsertCompanies(d);
            await dbHelper.deleteCompanies(id);
          }
        },
        'positions': {
          'endpoint': 'positions',
          'handler': (d, id) async {
            await dbHelper.upsertPositions(d);
            await dbHelper.deletePositions(id);
          }
        },
      };

      final fetchFutures = syncTasks.map((key, value) =>
          MapEntry(key, _fetchDelta(value['endpoint'] as String, null))); // Fetch all data
      final results = await Future.wait(fetchFutures.values);
      final resultData = Map.fromIterables(fetchFutures.keys, results);

      for (var entry in resultData.entries) {
        final key = entry.key;
        final result = entry.value;

        // Assuming the full list is returned in 'data' when lastSyncTimestamp is null
        if (result['success'] == true && result['data'] != null) {
          // Ensure 'data' is treated as a list, even if API might sometimes return a map for single results
          List<Map<String, dynamic>> allData = [];
          if (result['data'] is List) {
            allData = List<Map<String, dynamic>>.from(result['data']);
          } else if (result['data'] is Map) {
            // Handle cases where the API might return just a map if only one item exists
            // Or if the structure is like {'data': [...]} incorrectly
            var potentialList = (result['data'] as Map).values.firstWhere((v) => v is List, orElse: () => null);
            if (potentialList != null) {
              allData = List<Map<String, dynamic>>.from(potentialList);
            } else {
              debugPrint('ApiService: Unexpected data format for $key. Expected List, got Map.');
            }
          }

          // Since it's a full sync, we just upsert everything and don't delete
          if (allData.isNotEmpty) {
            await (syncTasks[key]!['handler'] as Function)(allData, []);
          } else if (result['data'] is Map && allData.isEmpty) {
            // If it was a map and we couldn't extract a list, log it.
            debugPrint('ApiService: Data for $key was a map, but could not extract list for handler.');
          }

        } else {
          debugPrint('ApiService: Failed to sync $key. Message: ${result['message']}');
        }
      }

      debugPrint('ApiService: Registration data sync complete.');
      return {'success': true, 'message': 'Registration data sync successful.'};
    } catch (e) {
      debugPrint('ApiService: Registration data sync failed: $e');
      return {'success': false, 'message': 'Registration data sync failed: $e'};
    }
  }
}

// =======================================================================
// Part 2 & 3: Marine, River, Air, and DatabaseHelper classes
//
// ... All of these class definitions have been REMOVED from this file
// and placed in their own respective files.
// =======================================================================