import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:inventory_system/services/api_service.dart';
import 'package:inventory_system/services/session_manager.dart';
import 'package:inventory_system/services/user_service.dart';

class ItemMovementService {
  Future<List<dynamic>> fetchItemMovements() async {
    final currentUser = SessionManager.instance.currentUser;

    if (currentUser == null) {
      throw Exception('User session not found.');
    }

    final userId = currentUser['id'];
    final currentUserRoles = currentUser['role'] as List<dynamic>? ?? [];
    final currentUserStore = currentUser['store']; // Get current user's store
    final currentUserDepartmentId = currentUser['department']?['departmentId'];

    List<dynamic> itemMovements = [];
    String apiUrl = '';
    HttpMethod method = HttpMethod.GET; // Default to GET, will be POST

    try {
      if (currentUserRoles.contains("Super Admin")) {
        // Super Admins see all item movements
        apiUrl = '${ApiService.baseUrl}/InvMainAPI/ItemMovementList';
        method = HttpMethod.POST;
      } else if (currentUserRoles.contains("Inventory Master")) {
        // Inventory Masters: fetch all movements, client-side filtering in UI based on currentUserStore
        apiUrl = '${ApiService.baseUrl}/InvMainAPI/ItemMovementList';
        method = HttpMethod.POST;
      } else {
        // Standard users: fetch only their item movements using specific API
        apiUrl = '${ApiService.baseUrl}/InvMainAPI/ItemMovementUser';
        method = HttpMethod.POST;
      }

      final uri = Uri.parse(apiUrl);
      final cookie = SessionManager.instance.getCookie();
      debugPrint("Fetching item movements from: $uri");

      final Map<String, String> headers = {
        'Content-Type': 'application/json; charset=UTF-8',
        if (cookie != null) 'Cookie': cookie,
      };

      http.Response response;
      if (method == HttpMethod.POST) {
        // For ItemMovementUser, need to send userId in body
        if (apiUrl == '${ApiService.baseUrl}/InvMainAPI/ItemMovementUser') {
          response = await http.post(
            uri,
            headers: headers,
            body: jsonEncode({'userId': userId}),
          );
        } else {
          response = await http.post(uri, headers: headers);
        }
      } else {
        response = await http.get(uri, headers: headers);
      }

      debugPrint('API Response Status: ${response.statusCode}');
      // debugPrint('API Response Body: ${response.body}');

      if (response.statusCode == 200) {
        itemMovements = response.body.isNotEmpty ? jsonDecode(response.body) : [];
      } else {
        throw Exception('Failed to load item movements. Status: ${response.statusCode}, Body: ${response.body}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } catch (e) {
      debugPrint('Error fetching item movements: $e');
      rethrow;
    }

    // Perform client-side filtering for Inventory Master
    if (currentUserRoles.contains("Inventory Master")) {
      // Filter by Store
      if (currentUserStore != null) {
        itemMovements = itemMovements
            .where((m) {
              final toStore = m['toStore'] as int?;
              final lastStore = m['lastStore'] as int?;
              return (toStore != null && toStore == currentUserStore) ||
                     (lastStore != null && lastStore == currentUserStore);
            })
            .toList();
      }

      // Filter by Department
      if (currentUserDepartmentId != null) {
        try {
          final userService = UserService();
          final allUsers = await userService.fetchUsers();
          final userDeptMap = {
            for (var u in allUsers)
              if (u['id'] != null && u['department'] != null)
                u['id']: u['department']['departmentId']
          };

          itemMovements = itemMovements.where((m) {
            final fromUser = m['lastUser'];
            final toUser = m['toUser'];
            final fromUserDept = userDeptMap[fromUser];
            final toUserDept = userDeptMap[toUser];

            return (fromUserDept == currentUserDepartmentId) || (toUserDept == currentUserDepartmentId);
          }).toList();

        } catch (e) {
          debugPrint("Error filtering by department: $e");
          // Optionally handle error, e.g., strictly return empty or allow all if fetch fails
        }
      }
    }

    return itemMovements;
  }

  Future<void> addItemMovement(Map<String, dynamic> data) async {
    final uri = Uri.parse('${ApiService.baseUrl}/InvMainAPI/AddItemMovement');
    final cookie = SessionManager.instance.getCookie();

    final Map<String, String> headers = {
      'Content-Type': 'application/json; charset=UTF-8',
      if (cookie != null) 'Cookie': cookie,
    };

    try {
      final response = await http.post(
        uri,
        headers: headers,
        body: jsonEncode(data),
      );

      if (response.statusCode != 200) {
        throw Exception('Failed to add item movement. Status: ${response.statusCode}, Body: ${response.body}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } catch (e) {
      debugPrint('Error adding item movement: $e');
      rethrow;
    }
  }

  Future<void> updateItemMovementMaster(Map<String, dynamic> data) async {
    final uri = Uri.parse('${ApiService.baseUrl}/InvMainAPI/UpdateItemMovementMaster');
    final cookie = SessionManager.instance.getCookie();

    final Map<String, String> headers = {
      'Content-Type': 'application/json; charset=UTF-8',
      if (cookie != null) 'Cookie': cookie,
    };

    try {
      final response = await http.post(
        uri,
        headers: headers,
        body: jsonEncode(data),
      );

      if (response.statusCode != 200) {
        throw Exception('Failed to update item movement master. Status: ${response.statusCode}, Body: ${response.body}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } catch (e) {
      debugPrint('Error updating item movement master: $e');
      rethrow;
    }
  }

  Future<void> updateItemMovementUser(Map<String, dynamic> data) async {
    final uri = Uri.parse('${ApiService.baseUrl}/InvMainAPI/UpdateItemMovementUser');
    final cookie = SessionManager.instance.getCookie();

    final Map<String, String> headers = {
      'Content-Type': 'application/json; charset=UTF-8',
      if (cookie != null) 'Cookie': cookie,
    };

    try {
      final response = await http.post(
        uri,
        headers: headers,
        body: jsonEncode(data),
      );

      if (response.statusCode != 200) {
        throw Exception('Failed to update item movement user. Status: ${response.statusCode}, Body: ${response.body}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } catch (e) {
      debugPrint('Error updating item movement user: $e');
      rethrow;
    }
  }

  Future<void> returnItemMovementUser(Map<String, dynamic> data) async {
    final uri = Uri.parse('${ApiService.baseUrl}/InvMainAPI/ReturnItemMovementUser');
    final cookie = SessionManager.instance.getCookie();

    final Map<String, String> headers = {
      'Content-Type': 'application/json; charset=UTF-8',
      if (cookie != null) 'Cookie': cookie,
    };

    try {
      final response = await http.post(
        uri,
        headers: headers,
        body: jsonEncode(data),
      );

      if (response.statusCode != 200) {
        throw Exception('Failed to return item movement user. Status: ${response.statusCode}, Body: ${response.body}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } catch (e) {
      debugPrint('Error returning item movement user: $e');
      rethrow;
    }
  }

  Future<void> stationItemMovementUser(Map<String, dynamic> data) async {
    final uri = Uri.parse('${ApiService.baseUrl}/InvMainAPI/StationItemMovementUser');
    final cookie = SessionManager.instance.getCookie();

    final Map<String, String> headers = {
      'Content-Type': 'application/json; charset=UTF-8',
      if (cookie != null) 'Cookie': cookie,
    };

    try {
      final response = await http.post(
        uri,
        headers: headers,
        body: jsonEncode(data),
      );

      if (response.statusCode != 200) {
        throw Exception('Failed to assign item movement to station. Status: ${response.statusCode}, Body: ${response.body}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } catch (e) {
      debugPrint('Error assigning item movement to station: $e');
      rethrow;
    }
  }

  Future<Map<String, dynamic>> getItemMovementById(int id) async {
    final uri = Uri.parse('${ApiService.baseUrl}/InvMainAPI/GetItemMovementById?id=$id');
    final cookie = SessionManager.instance.getCookie();

    final Map<String, String> headers = {
      'Content-Type': 'application/json; charset=UTF-8',
      if (cookie != null) 'Cookie': cookie,
    };

    try {
      final response = await http.get(uri, headers: headers); // Assuming GET for retrieval by ID

      if (response.statusCode == 200) {
        return response.body.isNotEmpty ? jsonDecode(response.body) : {};
      } else {
        throw Exception('Failed to get item movement. Status: ${response.statusCode}, Body: ${response.body}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } catch (e) {
      debugPrint('Error getting item movement: $e');
      rethrow;
    }
  }
}

enum HttpMethod { GET, POST } // Define HttpMethod enum
