import apiClient from "@/infrastructure/apiClient";
import apiPath from "@/infrastructure/apiPath";

export default {
  /**
   * Lấy danh sách khách hàng cần đối soát (API mới - CustomerReconciliationSlip)
   * Sử dụng SmartTableParam để phân trang, tìm kiếm và sắp xếp
   * @param {Object} searchModel - Model tìm kiếm theo SmartTableParam
   * @param {string} searchModel.Search.PredicateObject.Keyword - Từ khóa tìm kiếm
   * @param {DateTimeOffset} searchModel.Search.PredicateObject.FromDate - Ngày bắt đầu
   * @param {DateTimeOffset} searchModel.Search.PredicateObject.ToDate - Ngày kết thúc
   * @returns {Promise<Object>} Kết quả tìm kiếm với phân trang
   */
  async getCustomersOverview(searchModel) {
    try {
      // Build PredicateObject với các filter parameters
      const predicateObject = {
        Keyword: searchModel.Search?.PredicateObject?.Keyword || ""
      };

      // Thêm FromDate nếu có
      if (searchModel.Search?.PredicateObject?.FromDate) {
        predicateObject.FromDate = searchModel.Search.PredicateObject.FromDate;
      }

      // Thêm ToDate nếu có
      if (searchModel.Search?.PredicateObject?.ToDate) {
        predicateObject.ToDate = searchModel.Search.PredicateObject.ToDate;
      }

      const smartTableParam = {
        Pagination: {
          PageIndex: searchModel.Pagination.PageIndex,
          PageSize: searchModel.Pagination.PageSize
        },
        Search: {
          PredicateObject: predicateObject
        },
        Sort: {
          Predicate: searchModel.Sort?.Predicate || "LatestOrderDate",
          Reverse: searchModel.Sort?.Reverse ?? true
        }
      };

      const response = await apiClient.post(
        apiPath.reconciliation.getCustomersOverview,
        smartTableParam
      );

      // Map response từ API sang format internal
      // API trả về: { Items: [...], TotalRecord: number, NumberOfPages: number, ... }
      const data = response.data;
      const items = data.Items || data.Data || [];
      return {
        Items: items,
        TotalRecord: data.TotalRecord || data.NumberOfRecords || 0,
        NumberOfPages: data.NumberOfPages || 0,
        From: (searchModel.Pagination.PageIndex - 1) * searchModel.Pagination.PageSize + 1,
        To: (searchModel.Pagination.PageIndex - 1) * searchModel.Pagination.PageSize + items.length,
        LastPage: data.NumberOfPages || 0
      };
    } catch (error) {
      console.error("Error loading customers overview:", error);
      return {
        Items: [],
        TotalRecord: 0,
        NumberOfPages: 0,
        From: 0,
        To: 0,
        LastPage: 0
      };
    }
  },

  /**
   * Lấy danh sách đơn hàng có thể đối soát của một khách hàng
   * Sử dụng API CustomerReconciliationSlip/GetReconciliableOrders
   * @param {number} customerId - ID khách hàng
   * @returns {Promise<Array>} Danh sách đơn hàng có thể đối soát
   */
  async getReconciliableOrdersByCustomerId(customerId) {
    try {
      const response = await apiClient.get(
        apiPath.reconciliation.getReconciliableOrdersByCustomerId(customerId)
      );
      return response.data || [];
    } catch (error) {
      console.error("Error loading reconciliable orders for customer:", error);
      throw error;
    }
  },

  /**
   * Tạo phiếu đối soát khách hàng
   * Sử dụng API CustomerReconciliationSlip/Create
   * @param {Object|FormData} model - Model tạo phiếu đối soát (Object hoặc FormData nếu có file)
   * @param {number} model.CustomerId - ID khách hàng (bắt buộc)
   * @param {number[]} model.OrderIds - Danh sách ID đơn hàng (bắt buộc, tối thiểu 1 đơn)
   * @param {string} model.InternalNote - Ghi chú nội bộ (tùy chọn)
   * @param {File} model.Files - File đính kèm (tùy chọn, chỉ khi dùng FormData)
   * @param {string} model.TransferNote - Ghi chú chuyển khoản (tùy chọn, cho phiếu âm)
   * @param {string} model.TransferDate - Ngày chuyển khoản (tùy chọn, cho phiếu âm)
   * @param {string} model.BankAccountNumber - Số tài khoản ngân hàng (tùy chọn, cho phiếu dương)
   * @param {string} model.PaymentNote - Ghi chú thanh toán (tùy chọn, cho phiếu dương)
   * @returns {Promise<Object>} Kết quả tạo phiếu { Id: number, Message: string }
   */
  async createCustomerReconciliationSlip(model) {
    try {
      // Check if model is FormData (for file upload)
      if (model instanceof FormData) {
        // Send FormData directly (for multipart/form-data)
        const response = await apiClient.post(
          apiPath.reconciliation.createCustomerReconciliationSlip,
          model,
          {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          }
        );
        return response.data;
      } else {
        // Send as JSON (backward compatibility)
        const response = await apiClient.post(
          apiPath.reconciliation.createCustomerReconciliationSlip,
          {
            CustomerId: model.CustomerId,
            OrderIds: model.OrderIds,
            InternalNote: model.InternalNote || ""
          }
        );
        return response.data;
      }
    } catch (error) {
      console.error("Error creating customer reconciliation slip:", error);
      throw error;
    }
  },

  /**
   * Tìm kiếm danh sách phiếu đối soát khách hàng
   * Sử dụng API CustomerReconciliationSlip/Search
   * @param {Object} searchModel - Model tìm kiếm theo SmartTableParam
   * @param {Object} searchModel.Pagination - Phân trang
   * @param {number} searchModel.Pagination.PageIndex - Trang thứ mấy (bắt đầu từ 1)
   * @param {number} searchModel.Pagination.PageSize - Số bản ghi trên mỗi trang
   * @param {Object} searchModel.Search - Tìm kiếm
   * @param {string} searchModel.Search.PredicateObject.Keyword - Từ khóa (mã phiếu hoặc tên khách hàng)
   * @param {number} searchModel.Search.PredicateObject.Status - Trạng thái phiếu (1-8)
   * @param {Object} searchModel.Sort - Sắp xếp
   * @param {string} searchModel.Sort.Predicate - Tên trường sắp xếp
   * @param {boolean} searchModel.Sort.Reverse - true = giảm dần, false = tăng dần
   * @returns {Promise<Object>} Kết quả { NumberOfRecords, NumberOfPages, Data }
   */
  async searchCustomerReconciliationSlips(searchModel) {
    try {
      const response = await apiClient.post(
        apiPath.reconciliation.searchCustomerReconciliationSlips,
        searchModel
      );
      return response.data || {
        NumberOfRecords: 0,
        NumberOfPages: 0,
        Data: []
      };
    } catch (error) {
      console.error("Error searching customer reconciliation slips:", error);
      return {
        NumberOfRecords: 0,
        NumberOfPages: 0,
        Data: []
      };
    }
  },

  /**
   * Lấy chi tiết phiếu đối soát khách hàng theo ID
   * Sử dụng API CustomerReconciliationSlip/GetById/{id}
   * @param {number} id - ID phiếu đối soát
   * @returns {Promise<Object>} Chi tiết phiếu { Slip, Details, Logs }
   */
  async getCustomerReconciliationSlipById(id) {
    try {
      const response = await apiClient.get(
        apiPath.reconciliation.getCustomerReconciliationSlipById(id)
      );
      return response.data;
    } catch (error) {
      console.error("Error getting customer reconciliation slip by id:", error);
      throw error;
    }
  },

  /**
   * Tìm kiếm danh sách khách hàng cần đối soát
   * @param {Object} searchModel - Model tìm kiếm theo SmartTableParam
   * @param {number} reconciliationType - Loại đối soát (1: Tiền thu hộ, 2: Cước)
   * @returns {Promise<Object>} Kết quả tìm kiếm với phân trang
   */
  async getCustomersForReconciliation(searchModel, reconciliationType = 1) {
    const params = JSON.parse(JSON.stringify(searchModel));
    // Remove ReconciliationType from searchModel since it's now a URL parameter
    if (params.Search?.PredicateObject?.ReconciliationType) {
      reconciliationType = params.Search.PredicateObject.ReconciliationType;
      delete params.Search.PredicateObject.ReconciliationType;
    }

    var searchResult = await apiClient
      .post(
        apiPath.reconciliation.searchCustomersForReconciliation(
          reconciliationType
        ),
        params
      )
      .then((r) => {
        return r.data;
      })
      .catch((e) => {
        console.log(e);
        return {
          Items: [],
          TotalRecord: 0,
          NumberOfPages: 0,
          From: 0,
          To: 0,
          LastPage: 0,
        };
      });
    return searchResult;
  },

  /**
   * Tìm kiếm danh sách đơn hàng có thể đối soát của khách hàng
   * @param {Object} searchModel - Model tìm kiếm theo SmartTableParam
   * @param {number} searchModel.search.predicateObject.CustomerId - ID khách hàng (required)
   * @param {string} searchModel.search.predicateObject.Keyword - Từ khóa tìm kiếm
   * @param {number} reconciliationType - Loại đối soát (1: Tiền thu hộ, 2: Cước)
   * @returns {Promise<Object>} Kết quả tìm kiếm với phân trang
   */
  async getReconciliableOrders(searchModel, reconciliationType = 1) {
    const params = JSON.parse(JSON.stringify(searchModel));
    // Remove ReconciliationType from searchModel since it's now a URL parameter
    if (params.Search?.PredicateObject?.ReconciliationType) {
      reconciliationType = params.Search.PredicateObject.ReconciliationType;
      delete params.Search.PredicateObject.ReconciliationType;
    }

    var searchResult = await apiClient
      .post(
        apiPath.reconciliation.searchReconciliableOrders(reconciliationType),
        params
      )
      .then((r) => {
        return r.data;
      })
      .catch((e) => {
        console.log(e);
        return {
          Items: [],
          TotalRecord: 0,
          NumberOfPages: 0,
          From: 0,
          To: 0,
          LastPage: 0,
        };
      });
    return searchResult;
  },

  /**
   * Tạo đối soát mới
   * @param {Object} data - Dữ liệu tạo đối soát
   * @param {number} reconciliationType - Loại đối soát (1: Tiền thu hộ, 2: Cước)
   * @returns {Promise<Object>} Kết quả tạo đối soát
   */
  async create(data, reconciliationType = 1) {
    try {
      // Remove reconciliationType from data since it's now a URL parameter
      const submitData = { ...data };
      if (submitData.reconciliationType) {
        reconciliationType = submitData.reconciliationType;
        delete submitData.reconciliationType;
      }

      const response = await apiClient.post(
        apiPath.reconciliation.create(reconciliationType),
        submitData
      );
      return response.data;
    } catch (error) {
      console.error("Error creating reconciliation:", error);
      throw error;
    }
  },

  /**
   * Tìm kiếm phiếu đối soát
   * @param {Object} searchModel - Model tìm kiếm theo SmartTableParam
   * @param {number} reconciliationType - Loại đối soát (1: Tiền thu hộ, 2: Cước)
   * @returns {Promise<Object>} Kết quả tìm kiếm với phân trang
   */
  async search(searchModel, reconciliationType = 1) {
    try {
      const params = JSON.parse(JSON.stringify(searchModel));
      // Remove ReconciliationType from searchModel since it's now a URL parameter
      if (params.Search?.PredicateObject?.ReconciliationType) {
        reconciliationType = params.Search.PredicateObject.ReconciliationType;
        delete params.Search.PredicateObject.ReconciliationType;
      }

      const response = await apiClient.post(
        apiPath.reconciliation.search(reconciliationType),
        params
      );
      return (
        response.data || {
          items: [],
          totalRecord: 0,
          numberOfPages: 0,
          from: 0,
          to: 0,
          lastPage: 0,
        }
      );
    } catch (error) {
      console.error("Error searching reconciliations:", error);
      return {
        items: [],
        totalRecord: 0,
        numberOfPages: 0,
        from: 0,
        to: 0,
        lastPage: 0,
      };
    }
  },

  /**
   * Lấy chi tiết phiếu đối soát
   * @param {number} id - ID phiếu đối soát
   * @returns {Promise<Object>} Chi tiết phiếu đối soát
   */
  async getById(id) {
    try {
      const response = await apiClient.get(
        `${apiPath.reconciliation.getById}${id}`
      );
      return response.data;
    } catch (error) {
      console.error("Error getting reconciliation by id:", error);
      return null;
    }
  },

  /**
   * Xác nhận phiếu đối soát
   * @param {number} id - ID phiếu đối soát
   * @returns {Promise<Object>} Kết quả xác nhận
   */
  async confirm(id) {
    try {
      const response = await apiClient.put(
        `${apiPath.reconciliation.confirm}/${id}`
      );
      return response.data;
    } catch (error) {
      console.error("Error confirming reconciliation:", error);
      throw error;
    }
  },

  /**
   * Đánh dấu đã chuyển tiền (API cũ)
   * @param {number} id - ID phiếu đối soát
   * @param {string} transferDate - Ngày chuyển tiền
   * @returns {Promise<Object>} Kết quả cập nhật
   */
  async markAsTransferred(id, transferDate) {
    try {
      const response = await apiClient.post(
        apiPath.reconciliation.markAsTransferred,
        {
          id,
          transferDate,
        }
      );
      return response.data;
    } catch (error) {
      console.error("Error marking reconciliation as transferred:", error);
      throw error;
    }
  },

  /**
   * Cập nhật đã chuyển tiền (API mới)
   * @param {Object} transferModel - Model cập nhật chuyển tiền
   * @param {number} transferModel.reconciliationId - ID đối soát (bắt buộc)
   * @param {number} transferModel.transferMethod - Phương thức chuyển tiền
   * @param {string} transferModel.note - Ghi chú chuyển tiền (tùy chọn, max 1024 ký tự)
   * @param {string} transferModel.additionalInfo - Thông tin bổ sung (tùy chọn, max 2048 ký tự)
   * @param {boolean} transferModel.createTransaction - Có tạo giao dịch tự động không (mặc định: true)
   * @param {boolean} transferModel.sendNotification - Có gửi thông báo cho khách hàng không (mặc định: true)
   * @returns {Promise<Object>} Kết quả cập nhật
   */
  async updateTransferred(transferModel) {
    try {
      const response = await apiClient.put(
        apiPath.reconciliation.updateTransferred,
        transferModel
      );
      return response.data;
    } catch (error) {
      console.error("Error updating reconciliation transfer:", error);
      throw error;
    }
  },

  /**
   * Hủy phiếu đối soát
   * @param {number} id - ID phiếu đối soát
   * @param {string} reason - Lý do hủy
   * @returns {Promise<Object>} Kết quả hủy
   */
  async cancel(id, reason) {
    try {
      const response = await apiClient.post(apiPath.reconciliation.cancel, {
        ReconciliationId: id,
        CancelReason: reason,
      });
      return response.data;
    } catch (error) {
      console.error("Error cancelling reconciliation:", error);
      throw error;
    }
  },

  /**
   * Xuất Excel danh sách đối soát
   * @param {Object} searchModel - Model tìm kiếm
   * @param {number} reconciliationType - Loại đối soát (1: Tiền thu hộ, 2: Cước)
   * @returns {Promise<Blob>} File Excel
   */
  async export(searchModel, reconciliationType = 1) {
    try {
      const params = JSON.parse(JSON.stringify(searchModel));
      // Remove ReconciliationType from searchModel since it's now a URL parameter
      if (params.Search?.PredicateObject?.ReconciliationType) {
        reconciliationType = params.Search.PredicateObject.ReconciliationType;
        delete params.Search.PredicateObject.ReconciliationType;
      }

      params.isExport = true;

      const response = await apiClient.post(
        apiPath.reconciliation.export(reconciliationType),
        params,
        {
          responseType: "blob",
        }
      );
      return response.data;
    } catch (error) {
      console.error("Error exporting reconciliations:", error);
      throw error;
    }
  },

  /**
   * Duyệt phiếu đối soát khách hàng
   * Sử dụng API CustomerReconciliationSlip/Approve/{id}
   * @param {number} id - ID phiếu đối soát
   * @returns {Promise<Object>} Kết quả duyệt phiếu
   */
  async approveCustomerReconciliationSlip(id) {
    try {
      const response = await apiClient.put(
        apiPath.reconciliation.approveCustomerReconciliationSlip(id)
      );
      return response.data;
    } catch (error) {
      console.error("Error approving customer reconciliation slip:", error);
      throw error;
    }
  },

  /**
   * Từ chối phiếu đối soát khách hàng
   * Sử dụng API CustomerReconciliationSlip/Reject
   * @param {number} id - ID phiếu đối soát
   * @param {string} reason - Lý do từ chối
   * @returns {Promise<Object>} Kết quả từ chối phiếu
   */
  async rejectCustomerReconciliationSlip(id, reason) {
    try {
      const response = await apiClient.post(
        apiPath.reconciliation.rejectCustomerReconciliationSlip,
        {
          Id: id,
          Reason: reason
        }
      );
      return response.data;
    } catch (error) {
      console.error("Error rejecting customer reconciliation slip:", error);
      throw error;
    }
  },

  /**
   * Hoàn thành phiếu đối soát khách hàng
   * Sử dụng API CustomerReconciliationSlip/Complete
   * @param {Object} model - Model hoàn thành phiếu
   * @param {number} model.Id - ID phiếu đối soát
   * @param {string} model.ProofImageUrl - URL ảnh chứng từ (tùy chọn)
   * @param {string} model.Note - Ghi chú (tùy chọn)
   * @returns {Promise<Object>} Kết quả hoàn thành phiếu
   */
  async completeCustomerReconciliationSlip(model) {
    try {
      const response = await apiClient.post(
        apiPath.reconciliation.completeCustomerReconciliationSlip,
        {
          Id: model.Id,
          ProofImageUrl: model.ProofImageUrl || "",
          Note: model.Note || ""
        }
      );
      return response.data;
    } catch (error) {
      console.error("Error completing customer reconciliation slip:", error);
      throw error;
    }
  },

  /**
   * Xuất Excel danh sách phiếu đối soát
   * Sử dụng API CustomerReconciliationSlip/ExportExcel
   * @param {Object} model - Model xuất Excel
   * @returns {Promise<Object>} Response với DownloadUrl và metadata
   */
  async exportCustomerReconciliationSlipList(model) {
    try {
      const response = await apiClient.post(
        apiPath.reconciliation.exportCustomerReconciliationSlipList,
        model
      );
      return response.data;
    } catch (error) {
      console.error("Error exporting customer reconciliation slip list:", error);
      throw error;
    }
  },

  /**
   * Xuất Excel chi tiết phiếu đối soát
   * Sử dụng API CustomerReconciliationSlip/ExportExcelDetail/{id}
   * @param {number} id - ID phiếu đối soát
   * @param {Object} model - Model xuất Excel
   * @returns {Promise<Object>} Response với DownloadUrl và metadata
   */
  async exportCustomerReconciliationSlipDetail(id, model = {}) {
    try {
      const response = await apiClient.post(
        apiPath.reconciliation.exportCustomerReconciliationSlipDetail(id),
        {
          FileName: model.FileName || `ChiTietPhieu_${id}`,
          IncludeOrderDetails: model.IncludeOrderDetails !== false,
          IncludeApprovalInfo: model.IncludeApprovalInfo !== false,
          IncludeNotes: model.IncludeNotes !== false
        }
      );
      return response.data;
    } catch (error) {
      console.error("Error exporting customer reconciliation slip detail:", error);
      throw error;
    }
  },

  /**
   * Xuất Excel danh sách đơn hàng cần đối soát của khách hàng
   * Sử dụng API CustomerReconciliationSlip/ExportReconciliableOrders/{customerId}
   * @param {number} customerId - ID khách hàng
   * @param {Object} model - Model xuất Excel (tùy chọn)
   * @param {string} model.FileName - Tên file Excel (không bao gồm extension)
   * @param {boolean} model.IncludeOrderDetails - Có bao gồm chi tiết đơn hàng không
   * @param {string} model.FolderPath - Đường dẫn thư mục lưu file
   * @returns {Promise<Object>} Response với DownloadUrl và metadata
   */
  async exportReconciliableOrders(customerId, model = {}) {
    try {
      const response = await apiClient.post(
        apiPath.reconciliation.exportReconciliableOrders(customerId),
        {
          FileName: model.FileName || `DanhSachDonHangCanDoiSoat_${customerId}`,
          IncludeOrderDetails: model.IncludeOrderDetails !== false,
          FolderPath: model.FolderPath || ""
        }
      );
      return response.data;
    } catch (error) {
      console.error("Error exporting reconciliable orders:", error);
      throw error;
    }
  },

  /**
   * Download file Excel từ DownloadUrl
   * @param {string} downloadUrl - URL để download file (relative path)
   * @param {string} fileName - Tên file để lưu
   * @returns {Promise<Blob>} File Excel blob
   */
  async downloadExcelFile(downloadUrl, fileName) {
    try {
      const response = await apiClient.get(downloadUrl, {
        responseType: "blob"
      });
      return response.data;
    } catch (error) {
      console.error("Error downloading Excel file:", error);
      throw error;
    }
  },
};
