/// Order Remote Data Source
///
/// Handles API calls for order-related data.
library;

import 'package:worker/core/constants/api_constants.dart';
import 'package:worker/core/network/dio_client.dart';
import 'package:worker/features/orders/data/models/order_status_model.dart';
import 'package:worker/features/orders/data/models/payment_term_model.dart';

/// Order Remote Data Source
class OrderRemoteDataSource {
  const OrderRemoteDataSource(this._dioClient);

  final DioClient _dioClient;

  /// Get order status list
  ///
  /// Calls: POST /api/method/building_material.building_material.api.sales_order.get_order_status_list
  /// Returns: List of order statuses with labels and colors
  Future<List<OrderStatusModel>> getOrderStatusList() async {
    try {
      final response = await _dioClient.post<Map<String, dynamic>>(
        '${ApiConstants.frappeApiMethod}${ApiConstants.getOrderStatusList}',
        data: <String, dynamic>{},
      );

      final data = response.data;
      if (data == null) {
        throw Exception('No data received from getOrderStatusList API');
      }

      // API returns: { "message": [...] }
      final message = data['message'];
      if (message == null) {
        throw Exception('No message field in getOrderStatusList response');
      }

      final List<dynamic> statusList = message as List<dynamic>;
      return statusList
          .map((json) => OrderStatusModel.fromJson(json as Map<String, dynamic>))
          .toList();
    } catch (e) {
      throw Exception('Failed to get order status list: $e');
    }
  }

  /// Get payment terms list
  ///
  /// Calls: POST /api/method/frappe.client.get_list
  /// Body: { "doctype": "Payment Terms Template", "fields": ["name","custom_description"], "limit_page_length": 0 }
  /// Returns: List of payment terms with names and descriptions
  Future<List<PaymentTermModel>> getPaymentTermsList() async {
    try {
      final response = await _dioClient.post<Map<String, dynamic>>(
        '${ApiConstants.frappeApiMethod}${ApiConstants.frappeGetList}',
        data: {
          'doctype': 'Payment Terms Template',
          'fields': ['name', 'custom_description'],
          'limit_page_length': 0,
        },
      );

      final data = response.data;
      if (data == null) {
        throw Exception('No data received from getPaymentTermsList API');
      }

      // API returns: { "message": [...] }
      final message = data['message'];
      if (message == null) {
        throw Exception('No message field in getPaymentTermsList response');
      }

      final List<dynamic> termsList = message as List<dynamic>;
      return termsList
          .map((json) => PaymentTermModel.fromJson(json as Map<String, dynamic>))
          .toList();
    } catch (e) {
      throw Exception('Failed to get payment terms list: $e');
    }
  }

  /// Create new order
  ///
  /// Calls: POST /api/method/building_material.building_material.api.sales_order.save
  /// Body: {
  ///   "transaction_date": "2025-11-20",
  ///   "delivery_date": "2025-11-20",
  ///   "shipping_address_name": "...",
  ///   "customer_address": "...",
  ///   "description": "...",
  ///   "payment_terms": "...",
  ///   "items": [{"item_id": "...", "qty_entered": 0, "primary_qty": 0, "price_entered": 0}]
  /// }
  /// Returns: { "message": { "name": "SAL-ORD-2025-00001", ... } }
  Future<Map<String, dynamic>> createOrder({
    required List<Map<String, dynamic>> items,
    required Map<String, dynamic> deliveryAddress,
    required String paymentMethod,
    bool needsInvoice = false,
    bool needsNegotiation = false,
    String? notes,
  }) async {
    try {
      // Get current date for transaction and delivery
      final now = DateTime.now();
      final dateStr = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';

      // Format items for Frappe API
      final formattedItems = items.map((item) {
        return {
          'item_id': item['item_id'],
          'qty_entered': item['quantity'], // boxes/pieces (viên)
          'primary_qty': item['quantityConverted'], // m²
          'price_entered': item['price'],
        };
      }).toList();

      // Prepare request body in Frappe format
      final requestBody = {
        'transaction_date': dateStr,
        'delivery_date': dateStr,
        'shipping_address_name': deliveryAddress['name'] ?? '',
        'customer_address': deliveryAddress['name'] ?? '',
        'description': notes ?? 'Order from mobile app',
        'payment_terms': paymentMethod,
        'items': formattedItems,
      };

      final response = await _dioClient.post<Map<String, dynamic>>(
        '${ApiConstants.frappeApiMethod}${ApiConstants.createOrder}',
        data: requestBody,
      );

      final data = response.data;
      if (data == null) {
        throw Exception('No data received from createOrder API');
      }

      // Extract order info from Frappe response
      // Response format: { message: { success: true, message: "...", data: { name: "SAL-ORD-2025-00078", ... } } }
      final message = data['message'] as Map<String, dynamic>?;
      if (message == null) {
        throw Exception('No message field in createOrder response');
      }

      final orderData = message['data'] as Map<String, dynamic>?;
      if (orderData == null) {
        throw Exception('No data field in createOrder response');
      }

      final orderId = orderData['name'] as String?;
      if (orderId == null || orderId.isEmpty) {
        throw Exception('No order ID (name) in createOrder response');
      }

      // Return standardized response
      return {
        'orderId': orderId,
        'orderNumber': orderId,
        'fullResponse': orderData,
      };
    } catch (e) {
      throw Exception('Failed to create order: $e');
    }
  }

  /// Generate QR code for payment
  ///
  /// Calls: POST /api/method/building_material.building_material.api.v1.qrcode.generate
  /// Body: { "order_id": "SAL-ORD-2025-00048" }
  /// Returns: { "qr_code": "...", "amount": null, "transaction_id": "...", "bank_info": {...} }
  Future<Map<String, dynamic>> generateQrCode(String orderId) async {
    try {
      final response = await _dioClient.post<Map<String, dynamic>>(
        '${ApiConstants.frappeApiMethod}${ApiConstants.generateQrCode}',
        data: {'order_id': orderId},
      );

      final data = response.data;
      if (data == null) {
        throw Exception('No data received from generateQrCode API');
      }

      // Extract QR code info from Frappe response
      final message = data['message'] as Map<String, dynamic>?;
      if (message == null) {
        throw Exception('No message field in generateQrCode response');
      }

      return message;
    } catch (e) {
      throw Exception('Failed to generate QR code: $e');
    }
  }
}
