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<bool> 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<Either<String, OrderResponseModel>> 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<Either<String, SummaryResponseModel>> 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<Either<String, PaymentMethodResponseModel>>
      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<Either<String, bool>> addOrderItems(
    int orderId,
    List<Map<String, dynamic>> 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<Either<String, OrderDetailResponseModel>> 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<Either<String, PaymentSuccessResponseModel>> 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<Either<String, OrderResponseModel>> getOrder({
    int page = 1,
    int limit = Variables.defaultLimit,
    String status = 'completed',
    required DateTime dateFrom,
    required DateTime dateTo,
    String? search,
  }) async {
    try {
      final authData = await AuthLocalDataSource().getAuthData();

      Map<String, dynamic> params = {
        'page': page,
        'limit': limit,
        'status': status,
        'date_from': DateFormat('dd-MM-yyyy').format(dateFrom),
        'date_to': DateFormat('dd-MM-yyyy').format(dateTo),
      };

      if (search != null && search.isNotEmpty) {
        params['search'] = search;
      }

      final response = await dio.get(
        '${Variables.baseUrl}/api/v1/orders',
        queryParameters: params,
        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<Either<String, OrderDetailResponseModel>> 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<Either<String, OrderDetailResponseModel>> 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<Either<String, OrderDetailResponseModel>> addToOrder({
    required String orderId,
    required List<OrderItemRequest> 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<Either<String, bool>> refund({
    required String orderId,
    required String reason,
    required List<OrderItem> 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<Either<String, bool>> voidOrder({
    required String orderId,
    required String reason,
    String type = "ITEM", // TYPE: ALL, ITEM
    required List<OrderItem> 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<Either<String, bool>> 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');
    }
  }

  Future<Either<String, PaymentSuccessResponseModel>> createPaymentSplitBill(
      PaymentSplitBillRequest request) async {
    final authData = await AuthLocalDataSource().getAuthData();
    final url = '${Variables.baseUrl}/api/v1/orders/split-bill';

    try {
      final response = await dio.post(
        url,
        data: request.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');
    }
  }
}
