/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ShipmentStatus } from "@/Constant/enums";
import { api } from "./Api";

export async function getSingleSettledView(id: any) {
    const [, data] = await api.get(
      `/customer/shipment/details//${id}`,
      true
    );
  
    return data?.data;
}

export async function createShipment(data: any) {
  const [, response] = await api.post("/customer/shipment/create", data, true);
  return response;
}

export async function updateShipment(data: any) {
  if(data?.status === ShipmentStatus.Shipped)
    {
      const responseStatus = await shipmentStatus(data)
      return responseStatus
    }
  const [, response] = await api.put("/customer/shipment/update", data, true);
  return response; 
}

export async function shipmentStatus(data: any) {
  const [, response] = await api.post("/customer/shipment/status/update", data, true);
  // return response;
  const details = await getShipmentDetails(data?.shipment_id)
  return {...response, data: details?.shipmentDetails};
}

export async function listShipments(filters?: any): Promise<any[]> {
  const queryParams: any = {};
  const rawParams = {
    page: filters?.page,
    limit: filters?.limit || "",
    search: filters?.search || "",
    shipment_id: filters?.shipmentId || "",
    status: filters?.status || "",
    type: filters?.type || "",
    shipment_type_for_admin: filters?.shipmentTypeForAdmin || "",
    mode: filters?.mode || "",
    shipment_date_start: filters?.shipmentDateRange?.start || "",
    shipment_date_end: filters?.shipmentDateRange?.end || "",
    eta_date_start: filters?.etaDateRange?.start || "",
    eta_date_end: filters?.etaDateRange?.end || "",
  };

  Object.entries(rawParams).forEach(([key, value]) => {
    if (value !== undefined && value !== null && value !== "") {
      queryParams[key] = value;
    }
  });
  const [, response] = await api.get(
    "/customer/shipment/list",
    true,
    {},
    queryParams
  );
  return response?.data?.data || response?.data || [];
}

export async function getShipmentDetails(id: number) {
  const [, response] = await api.get(
    `/customer/shipment/details/${id}`,
    true,
    {}
  );
  return response?.data?.data || response?.data || [];
}

/**
 * Manifest upload API functions for shipment management
 * 
 * @example
 * ```typescript
 * // Basic usage
 * const result = await uploadManifest({
 *   manifest_file: fileInput.files[0],
 *   shipment_id: 123
 * });
 * 
 * if (result.success) {
 *   console.log('Upload successful:', result.data);
 * } else {
 *   console.error('Upload failed:', result.error);
 * }
 * 
 * // With metadata
 * const result = await uploadManifest({
 *   manifest_file: fileInput.files[0],
 *   shipment_id: 123,
 *   metadata: {
 *     uploaded_at: new Date().toISOString(),
 *     file_name: fileInput.files[0].name,
 *     file_size: fileInput.files[0].size,
 *     user_id: currentUser.id
 *   }
 * });
 * ```
 */

export interface ManifestUploadData {
  manifest_file: File;
  shipment_id: number | string;
  metadata?: {
    uploaded_at?: string;
    file_name?: string;
    file_size?: number;
    user_id?: string | number;
  };
}

export interface ManifestUploadResponse {
  success: boolean;
  message?: string;
  data?: any;
  error?: string;
}

/**
 * Creates FormData for manifest upload with proper validation
 */
function createManifestFormData(data: ManifestUploadData): FormData {
  const formData = new FormData();
  
  // Required fields
  formData.append('manifest_file', data.manifest_file);
  formData.append('shipment_id', data.shipment_id.toString());
  
  // Optional metadata
  if (data.metadata) {
    if (data.metadata.uploaded_at) {
      formData.append('uploaded_at', data.metadata.uploaded_at);
    }
    if (data.metadata.file_name) {
      formData.append('file_name', data.metadata.file_name);
    }
    if (data.metadata.file_size) {
      formData.append('file_size', data.metadata.file_size.toString());
    }
    if (data.metadata.user_id) {
      formData.append('user_id', data.metadata.user_id.toString());
    }
  }
  
  return formData;
}

export async function uploadManifest(
  data: ManifestUploadData,
  onProgress?: (progress: number) => void
): Promise<ManifestUploadResponse> {
  try {
    // Validate input data
    if (!data.manifest_file || !(data.manifest_file instanceof File)) {
      throw new Error('Invalid manifest file provided');
    }

    if (!data.shipment_id) {
      throw new Error('Shipment ID is required');
    }

    // Validate file type (Excel files)
    const allowedTypes = [
      'application/vnd.ms-excel',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'application/vnd.ms-excel.sheet.macroEnabled.12'
    ];
    
    if (!allowedTypes.includes(data.manifest_file.type) && 
        !data.manifest_file.name.toLowerCase().endsWith('.xlsx') &&
        !data.manifest_file.name.toLowerCase().endsWith('.xls')) {
      throw new Error('Invalid file type. Please upload an Excel file (.xlsx or .xls)');
    }

    // Validate file size (max 10MB)
    const maxSize = 10 * 1024 * 1024; // 10MB
    if (data.manifest_file.size > maxSize) {
      throw new Error('File size too large. Maximum size is 10MB');
    }

    // Create FormData for file upload
    const formData = createManifestFormData(data);

    const [success, response, status] = await api.postFormData(
      "/customer/shipment/manifest/upload", 
      formData, 
      true
    );

    if (success) {
      return {
        success: true,
        data: response,
        message: 'Manifest uploaded successfully'
      };
    } else {
      return {
        success: false,
        error: response?.message || 'Failed to upload manifest',
        data: response
      };
    }
  } catch (error: any) {
    console.error('Error uploading manifest:', error);
    return {
      success: false,
      error: error.message || 'An unexpected error occurred during upload'
    };
  }
}

/**
 * Manifest Column Mapping API
 * Maps columns from uploaded manifest files to system fields
 */

export interface ManifestColumnMapping {
  [key: string]: number; // Field name -> Column index mapping
}

export interface ManifestColumnMappingData {
  shipment_id: number | string;
  manifest_columns: ManifestColumnMapping[];
}

export interface ManifestColumnMappingResponse {
  success: boolean;
  message?: string;
  data?: any;
  error?: string;
}

/**
 * Maps manifest columns to system fields for a specific shipment
 * 
 * @example
 * ```typescript
 * const result = await mapManifestColumns({
 *   shipment_id: 123,
 *   manifest_columns: [
 *     { "delybell_order_id": 3 },
 *     { "receiver_name": 12 },
 *     { "receiver_phone": 13 },
 *     { "receiver_address": 14 }
 *   ]
 * });
 * 
 * if (result.success) {
 *   console.log('Column mapping successful:', result.data);
 * } else {
 *   console.error('Mapping failed:', result.error);
 * }
 * ```
 */
export async function mapManifestColumns(
  data: ManifestColumnMappingData
): Promise<ManifestColumnMappingResponse> {
  try {
    // Validate input data
    if (!data.shipment_id) {
      throw new Error('Shipment ID is required');
    }

    if (!data.manifest_columns || !Array.isArray(data.manifest_columns) || data.manifest_columns.length === 0) {
      throw new Error('Manifest columns mapping is required and must be a non-empty array');
    }

    // Validate column mapping structure
    for (const columnMapping of data.manifest_columns) {
      if (typeof columnMapping !== 'object' || columnMapping === null) {
        throw new Error('Each column mapping must be an object');
      }

      const keys = Object.keys(columnMapping);
      if (keys.length !== 1) {
        throw new Error('Each column mapping must have exactly one key-value pair');
      }

      const [fieldName, columnIndex] = keys;
      if (typeof fieldName !== 'string' || fieldName.trim() === '') {
        throw new Error('Field name must be a non-empty string');
      }

      if (typeof columnIndex !== 'number' || columnIndex < 0) {
        throw new Error('Column index must be a non-negative number');
      }
    }

    // Send mapping request
    const [success, response, status] = await api.post(
      "/customer/shipment/manifest/column/mapping",
      data,
      false
    );

    if (success) {
      return {
        success: true,
        data: response,
        message: 'Manifest column mapping successful'
      };
    } else {
      return {
        success: false,
        error: response?.message || 'Failed to map manifest columns',
        data: response
      };
    }
  } catch (error: any) {
    console.error('Error mapping manifest columns:', error);
    return {
      success: false,
      error: error.message || 'An unexpected error occurred during column mapping'
    };
  }
}

export async function manifestColumnMapping(
  payload: any
): Promise<ManifestColumnMappingResponse> {
  try {
    // Validate input data
    if (!payload.shipment_id) {
      throw new Error('Shipment ID is required');
    }

    if (!payload.manifest_columns || !Array.isArray(payload.manifest_columns) || payload.manifest_columns.length === 0) {
      throw new Error('Manifest columns mapping is required and must be a non-empty array');
    }

    // Validate column mapping structure
    for (const columnMapping of payload.manifest_columns) {
      if (typeof columnMapping !== 'object' || columnMapping === null) {
        throw new Error('Each column mapping must be an object');
      }

      const keys = Object.keys(columnMapping);
      if (keys.length !== 1) {
        throw new Error('Each column mapping must have exactly one key-value pair');
      }

      const [fieldName, columnIndex] = keys;
      if (typeof fieldName !== 'string' || fieldName.trim() === '') {
        throw new Error('Field name must be a non-empty string');
      }
    }

    // Send mapping request
    const [success, response, status] = await api.post(
      "/customer/shipment/manifest/column/mapping",
      payload,
      true
    );

    return response;
  } catch (error: any) {
    console.error('Error mapping manifest columns:', error);
    return {
      success: false,
      message: error.message || 'An unexpected error occurred during column mapping'
    };
  }
}
/**
 * Gets the current column mapping for a specific shipment
 */
export async function getManifestColumnMapping(
  shipmentId: number | string
): Promise<ManifestColumnMappingResponse> {
  try {
    if (!shipmentId) {
      throw new Error('Shipment ID is required');
    }

    const [success, response, status] = await api.get(
      `/customer/shipment/manifest/column/mapping/${shipmentId}`,
      false
    );

    if (success) {
      return {
        success: true,
        data: response,
        message: 'Column mapping retrieved successfully'
      };
    } else {
      return {
        success: false,
        error: response?.message || 'Failed to retrieve column mapping',
        data: response
      };
    }
  } catch (error: any) {
    console.error('Error retrieving manifest column mapping:', error);
    return {
      success: false,
      error: error.message || 'An unexpected error occurred while retrieving column mapping'
    };
  }
}

/**
 * Updates existing manifest column mapping
 */
export async function updateManifestColumnMapping(
  data: ManifestColumnMappingData
): Promise<ManifestColumnMappingResponse> {
  try {
    // Validate input data (same as mapManifestColumns)
    if (!data.shipment_id) {
      throw new Error('Shipment ID is required');
    }

    if (!data.manifest_columns || !Array.isArray(data.manifest_columns) || data.manifest_columns.length === 0) {
      throw new Error('Manifest columns mapping is required and must be a non-empty array');
    }

    // Validate column mapping structure
    for (const columnMapping of data.manifest_columns) {
      if (typeof columnMapping !== 'object' || columnMapping === null) {
        throw new Error('Each column mapping must be an object');
      }

      const keys = Object.keys(columnMapping);
      if (keys.length !== 1) {
        throw new Error('Each column mapping must have exactly one key-value pair');
      }

      const [fieldName, columnIndex] = keys;
      if (typeof fieldName !== 'string' || fieldName.trim() === '') {
        throw new Error('Field name must be a non-empty string');
      }

      if (typeof columnIndex !== 'number' || columnIndex < 0) {
        throw new Error('Column index must be a non-negative number');
      }
    }

    // Send update request
    const [success, response, status] = await api.put(
      "/customer/shipment/manifest/column/mapping",
      data,
      false
    );

    if (success) {
      return {
        success: true,
        data: response,
        message: 'Manifest column mapping updated successfully'
      };
    } else {
      return {
        success: false,
        error: response?.message || 'Failed to update manifest column mapping',
        data: response
      };
    }
  } catch (error: any) {
    console.error('Error updating manifest column mapping:', error);
    return {
      success: false,
      error: error.message || 'An unexpected error occurred during column mapping update'
    };
  }
}

export async function getWarehouse(filters?: any): Promise<any[]> {
  const queryParams: any = {};
  const rawParams = {
    page: filters?.page,
    limit: filters?.limit || "",
    search: filters?.search || "",
  };

  Object.entries(rawParams).forEach(([key, value]) => {
    if (value !== undefined && value !== null && value !== "") {
      queryParams[key] = value;
    }
  });

  const [, response] = await api.get(
    "/customer/master/warehouse/list/all",
    true,
    {},
    queryParams
  );
  return response?.data?.data || response?.data || [];
}

export async function updateShipmentStatus(id: number, data: any) {
  const [, response] = await api.put(
    `/customer/shipment/status/update/${id}`,
    data,
    true
  );
  return response;
}