/// Order Repository Implementation
///
/// Implements the order repository interface.
library;

import 'package:worker/features/orders/data/datasources/order_remote_datasource.dart';
import 'package:worker/features/orders/data/datasources/order_status_local_datasource.dart';
import 'package:worker/features/orders/data/models/order_detail_model.dart';
import 'package:worker/features/orders/data/models/order_model.dart';
import 'package:worker/features/orders/domain/entities/order.dart';
import 'package:worker/features/orders/domain/entities/order_detail.dart';
import 'package:worker/features/orders/domain/entities/order_status.dart';
import 'package:worker/features/orders/domain/entities/payment_term.dart';
import 'package:worker/features/orders/domain/repositories/order_repository.dart';

/// Order Repository Implementation
class OrderRepositoryImpl implements OrderRepository {
  const OrderRepositoryImpl(
    this._remoteDataSource,
    this._statusLocalDataSource,
  );

  final OrderRemoteDataSource _remoteDataSource;
  final OrderStatusLocalDataSource _statusLocalDataSource;

  @override
  Future<List<Order>> getOrdersList({
    int limitStart = 0,
    int limitPageLength = 0,
  }) async {
    try {
      final ordersData = await _remoteDataSource.getOrdersList(
        limitStart: limitStart,
        limitPageLength: limitPageLength,
      );
      // Convert JSON → Model → Entity
      return ordersData
          .map((json) => OrderModel.fromJson(json).toEntity())
          .toList();
    } catch (e) {
      throw Exception('Failed to get orders list: $e');
    }
  }

  @override
  Future<OrderDetail> getOrderDetail(String orderId) async {
    try {
      final detailData = await _remoteDataSource.getOrderDetail(orderId);
      // Convert JSON → Model → Entity
      return OrderDetailModel.fromJson(detailData).toEntity();
    } catch (e) {
      throw Exception('Failed to get order detail: $e');
    }
  }

  @override
  Future<List<OrderStatus>> getOrderStatusList() async {
    try {
      // Try to get from cache first
      if (_statusLocalDataSource.hasCachedData()) {
        final cachedModels = _statusLocalDataSource.getCachedStatusList();
        if (cachedModels.isNotEmpty) {
          return cachedModels.map((model) => model.toEntity()).toList();
        }
      }

      // Fetch from API
      final models = await _remoteDataSource.getOrderStatusList();

      // Cache the results
      await _statusLocalDataSource.cacheStatusList(models);

      // Return entities
      return models.map((model) => model.toEntity()).toList();
    } catch (e) {
      // If API fails, try to return cached data
      final cachedModels = _statusLocalDataSource.getCachedStatusList();
      if (cachedModels.isNotEmpty) {
        return cachedModels.map((model) => model.toEntity()).toList();
      }
      throw Exception('Failed to get order status list: $e');
    }
  }

  @override
  Future<List<PaymentTerm>> getPaymentTermsList() async {
    try {
      final models = await _remoteDataSource.getPaymentTermsList();
      return models.map((model) => model.toEntity()).toList();
    } catch (e) {
      throw Exception('Failed to get payment terms list: $e');
    }
  }

  @override
  Future<Map<String, dynamic>> createOrder({
    required List<Map<String, dynamic>> items,
    required Map<String, dynamic> deliveryAddress,
    required String paymentMethod,
    bool needsInvoice = false,
    bool ignorePricingRule = false,
    bool contractRequest = false,
    String? notes,
  }) async {
    try {
      return await _remoteDataSource.createOrder(
        items: items,
        deliveryAddress: deliveryAddress,
        paymentMethod: paymentMethod,
        needsInvoice: needsInvoice,
        ignorePricingRule: ignorePricingRule,
        contractRequest: contractRequest,
        notes: notes,
      );
    } catch (e) {
      throw Exception('Failed to create order: $e');
    }
  }

  @override
  Future<Map<String, dynamic>> generateQrCode(String orderId) async {
    try {
      return await _remoteDataSource.generateQrCode(orderId);
    } catch (e) {
      throw Exception('Failed to generate QR code: $e');
    }
  }

  @override
  Future<Map<String, dynamic>> uploadBill({
    required String filePath,
    required String orderId,
  }) async {
    try {
      return await _remoteDataSource.uploadBill(
        filePath: filePath,
        orderId: orderId,
      );
    } catch (e) {
      throw Exception('Failed to upload bill: $e');
    }
  }

  @override
  Future<void> updateOrderAddress({
    required String orderId,
    required String shippingAddressName,
    required String customerAddress,
  }) async {
    try {
      await _remoteDataSource.updateOrderAddress(
        orderId: orderId,
        shippingAddressName: shippingAddressName,
        customerAddress: customerAddress,
      );
    } catch (e) {
      throw Exception('Failed to update order address: $e');
    }
  }

  @override
  Future<void> cancelOrder(String orderId) async {
    try {
      await _remoteDataSource.cancelOrder(orderId);
    } catch (e) {
      throw Exception('Failed to cancel order: $e');
    }
  }
}
