import 'dart:convert'; import 'dart:developer'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:enaklo_pos/core/constants/variables.dart'; import 'package:enaklo_pos/core/network/dio_client.dart'; import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart'; import 'package:enaklo_pos/data/models/request/payment_request.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:enaklo_pos/data/models/response/payment_method_response_model.dart'; import 'package:enaklo_pos/data/models/response/payment_methods_response_model.dart'; import 'package:enaklo_pos/data/models/response/payment_response_model.dart'; import 'package:enaklo_pos/data/models/response/summary_response_model.dart'; import 'package:enaklo_pos/presentation/home/models/order_model.dart'; import 'package:enaklo_pos/presentation/home/models/order_request.dart'; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; class OrderRemoteDatasource { final Dio dio = DioClient.instance; //save order to remote server Future saveOrder(OrderModel orderModel) async { final authData = await AuthLocalDataSource().getAuthData(); print("🌐 API CALL: saveOrder"); print("📡 URL: ${Variables.baseUrl}/api/save-order"); print("🔑 Token: ${authData.token?.substring(0, 20)}..."); try { final response = await http.post( Uri.parse('${Variables.baseUrl}/api/save-order'), body: orderModel.toJson(), headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ); print("📥 HTTP Status Code: ${response.statusCode}"); print("📥 Response Body: ${response.body}"); print("📥 Response Headers: ${response.headers}"); if (response.statusCode == 200) { print("✅ API call successful - Order saved to server"); return true; } else { print("❌ API call failed - Status: ${response.statusCode}"); print("❌ Error Response: ${response.body}"); return false; } } catch (e) { print("💥 API call error: $e"); return false; } } Future> getOrderByRangeDate( String stratDate, String endDate, ) async { try { final authData = await AuthLocalDataSource().getAuthData(); final response = await http.get( Uri.parse( '${Variables.baseUrl}/api/orders?start_date=$stratDate&end_date=$endDate'), headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ); print("📥 HTTP Status Code: ${response.statusCode}"); print("📥 Response Body: ${response.body}"); print("📥 Response Headers: ${response.headers}"); if (response.statusCode == 200) { print("✅ getOrderByRangeDate API call successful"); return Right(OrderResponseModel.fromJson(response.body)); } else { print( "❌ getOrderByRangeDate API call failed - Status: ${response.statusCode}"); print("❌ Error Response: ${response.body}"); return const Left("Failed Load Data"); } } catch (e) { print("💥 getOrderByRangeDate API call error: $e"); return Left("Failed: $e"); } } Future> getSummaryByRangeDate( String stratDate, String endDate, ) async { try { final authData = await AuthLocalDataSource().getAuthData(); final response = await http.get( Uri.parse( '${Variables.baseUrl}/api/summary?start_date=$stratDate&end_date=$endDate'), headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ); print("📡 URL: ${response.request!.url}"); print("📥 HTTP Status Code: ${response.statusCode}"); print("📥 Response Body: ${response.body}"); print("📥 Response Headers: ${response.headers}"); if (response.statusCode == 200) { print("✅ getSummaryByRangeDate API call successful"); return Right(SummaryResponseModel.fromJson(response.body)); } else { print( "❌ getSummaryByRangeDate API call failed - Status: ${response.statusCode}"); print("❌ Error Response: ${response.body}"); return const Left("Failed Load Data"); } } catch (e) { print("💥 getSummaryByRangeDate API call error: $e"); return Left("Failed: $e"); } } Future> getPaymentMethodByRangeDate( String startDate, String endDate, ) async { try { final authData = await AuthLocalDataSource().getAuthData(); final response = await http.get( Uri.parse( '${Variables.baseUrl}/api/order-paymentmethod?start_date=$startDate&end_date=$endDate'), headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ); print("📥 Payment Method HTTP Status Code: ${response.statusCode}"); print("📥 Payment Method Response Body: ${response.body}"); print("📥 Payment Method Response Headers: ${response.headers}"); if (response.statusCode == 200) { print("✅ getPaymentMethodByRangeDate API call successful"); return Right(PaymentMethodResponseModel.fromJson(response.body)); } else { print( "❌ getPaymentMethodByRangeDate API call failed - Status: ${response.statusCode}"); print("❌ Error Response: ${response.body}"); return const Left("Failed Load Payment Method Data"); } } catch (e) { print("💥 getPaymentMethodByRangeDate API call error: $e"); return Left("Failed: $e"); } } Future> addOrderItems( int orderId, List> orderItems, ) async { try { final authData = await AuthLocalDataSource().getAuthData(); final response = await http.post( Uri.parse('${Variables.baseUrl}/api/orders/add-items'), headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: jsonEncode({ 'order_id': orderId, 'order_items': orderItems, }), ); print("📥 Add Order Items HTTP Status Code: ${response.statusCode}"); print("📥 Add Order Items Response Body: ${response.body}"); print("📥 Add Order Items Response Headers: ${response.headers}"); if (response.statusCode == 200) { print("✅ addOrderItems API call successful"); return const Right(true); } else { print( "❌ addOrderItems API call failed - Status: ${response.statusCode}"); print("❌ Error Response: ${response.body}"); return Left("Failed to add order items: ${response.body}"); } } catch (e) { print("💥 addOrderItems API call error: $e"); return Left("Failed: $e"); } } // New Api Future> createOrder( OrderRequestModel orderModel, ) async { final authData = await AuthLocalDataSource().getAuthData(); final url = '${Variables.baseUrl}/api/v1/orders'; try { final response = await dio.post( url, data: orderModel.toMap(), options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { return Right(OrderDetailResponseModel.fromMap(response.data)); } else { return const Left('Gagal membuat pesanan'); } } on DioException catch (e) { final errorMessage = e.response?.data['message'] ?? 'Terjadi kesalahan, coba lagi nanti.'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return const Left('Terjadi kesalahan tak terduga'); } } Future> createPayment( PaymentRequestModel orderModel) async { final authData = await AuthLocalDataSource().getAuthData(); final url = '${Variables.baseUrl}/api/v1/payments'; try { final response = await dio.post( url, data: orderModel.toMap(), options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { return Right(PaymentSuccessResponseModel.fromMap(response.data)); } else { return const Left('Gagal membuat pembayaran'); } } on DioException catch (e) { final errorMessage = e.response?.data['message'] ?? 'Terjadi kesalahan, coba lagi nanti.'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return const Left('Terjadi kesalahan tak terduga'); } } Future> getOrder({ int page = 1, int limit = Variables.defaultLimit, String status = 'completed', required DateTime dateFrom, required DateTime dateTo, }) async { try { final authData = await AuthLocalDataSource().getAuthData(); final response = await dio.get( '${Variables.baseUrl}/api/v1/orders', queryParameters: { 'page': page, 'limit': limit, 'status': status, 'date_from': DateFormat('dd-MM-yyyy').format(dateFrom), 'date_to': DateFormat('dd-MM-yyyy').format(dateTo), }, options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { return Right(OrderResponseModel.fromMap(response.data)); } else { log("❌ getOrderByRangeDate API call failed - Status: ${response.statusCode}"); return const Left("Failed Load Data"); } } on DioException catch (e) { final errorMessage = 'Something went wrong'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return Left("Unexpected Error: $e"); } } Future> getOrderById( {required String orderId}) async { try { final authData = await AuthLocalDataSource().getAuthData(); final response = await dio.get( '${Variables.baseUrl}/api/v1/orders/$orderId', options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { return Right(OrderDetailResponseModel.fromMap(response.data)); } else { log("❌ OrderDetailResponseModel API call failed - Status: ${response.statusCode}"); return const Left("Failed Load Data"); } } on DioException catch (e) { final errorMessage = 'Something went wrong'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return Left("Unexpected Error: $e"); } } Future> createOrderWithPayment( OrderRequestModel orderModel, PaymentMethod payment, ) async { final authData = await AuthLocalDataSource().getAuthData(); final url = '${Variables.baseUrl}/api/v1/orders'; try { final response = await dio.post( url, data: orderModel.toMap(), options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { final data = OrderDetailResponseModel.fromMap(response.data); final orderData = data.data; final paymentRequest = PaymentRequestModel( orderId: orderData?.id, amount: orderData?.totalAmount, paymentMethodId: payment.id, splitDescription: '', splitNumber: 1, splitTotal: 1, paymentOrderItems: orderData?.orderItems ?.map((item) => PaymentOrderItemModel( amount: item.totalPrice, orderItemId: item.id, )) .toList(), ); createPayment(paymentRequest); return Right(data); } else { return const Left('Gagal membuat pesanan'); } } on DioException catch (e) { final errorMessage = e.response?.data['message'] ?? 'Terjadi kesalahan, coba lagi nanti.'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return const Left('Terjadi kesalahan tak terduga'); } } Future> addToOrder({ required String orderId, required List orderItems, }) async { final authData = await AuthLocalDataSource().getAuthData(); final url = '${Variables.baseUrl}/api/v1/orders/$orderId/add-items'; try { final response = await dio.post( url, data: { "order_items": orderItems.map((item) => item.toMap()).toList(), 'notes': '', }, options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { final data = OrderDetailResponseModel.fromMap(response.data); return Right(data); } else { return const Left('Gagal menambahkan pesanan pesanan'); } } on DioException catch (e) { final errorMessage = e.response?.data['message'] ?? 'Terjadi kesalahan, coba lagi nanti.'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return const Left('Terjadi kesalahan tak terduga'); } } Future> refund({ required String orderId, required String reason, required List orderItems, }) async { final authData = await AuthLocalDataSource().getAuthData(); final url = '${Variables.baseUrl}/api/v1/orders/$orderId/refund'; final int refundAmount = orderItems.fold( 0, (sum, item) => sum + ((item.unitPrice ?? 0) * (item.quantity ?? 0)), ); try { final response = await dio.post( url, data: { 'refund_amount': refundAmount, "order_items": orderItems .map((item) => { 'order_item_id': item.id, "refund_quantity": item.quantity, "refund_amount": item.totalPrice, "reason": "" }) .toList(), 'reason': reason, }, options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { return Right(true); } else { return const Left('Gagal refund'); } } on DioException catch (e) { final errorMessage = e.response?.data['message'] ?? 'Terjadi kesalahan, coba lagi nanti.'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return const Left('Terjadi kesalahan tak terduga'); } } Future> voidOrder({ required String orderId, required String reason, String type = "ITEM", // TYPE: ALL, ITEM required List orderItems, }) async { final authData = await AuthLocalDataSource().getAuthData(); final url = '${Variables.baseUrl}/api/v1/orders/void'; try { final response = await dio.post( url, data: { 'order_id': orderId, 'type': orderItems.isEmpty ? "ALL" : type, 'reason': reason, "items": orderItems .map((item) => { 'order_item_id': item.id, "quantity": item.quantity, }) .toList(), }, options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { return Right(true); } else { return const Left('Gagal refund'); } } on DioException catch (e) { final errorMessage = e.response?.data['message'] ?? 'Terjadi kesalahan, coba lagi nanti.'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return const Left('Terjadi kesalahan tak terduga'); } } Future> refundPayment({ required String orderId, required String reason, required int refundAmount, }) async { final authData = await AuthLocalDataSource().getAuthData(); final url = '${Variables.baseUrl}/api/v1/orders/$orderId/refund'; try { final response = await dio.post( url, data: { 'refund_amount': refundAmount, 'reason': reason, }, options: Options( headers: { 'Authorization': 'Bearer ${authData.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, ), ); if (response.statusCode == 200) { return Right(true); } else { return const Left('Gagal refund'); } } on DioException catch (e) { final errorMessage = 'Terjadi kesalahan coba lagi nanti'; log("💥 Dio error: ${e.message}"); log("💥 Dio response: ${e.response?.data}"); return Left(errorMessage); } catch (e) { log("💥 Unexpected error: $e"); return const Left('Terjadi kesalahan tak terduga'); } } }