import { z } from 'zod';

/**
 * Schema for validating order search/filter parameters (query params).
 * Used to validate input when searching for orders via API.
 */
export const findOrdersSchema = z.object({
  codfilial: z.union([z.string(), z.array(z.string())]).optional(),
  store: z.union([z.string(), z.array(z.string())]).optional(),
  includeCheckout: z.coerce.boolean().optional(),
  filialretira: z.string().optional(),
  carrier: z.string().optional(),
  cnpj: z.string().optional(),

  hour: z.coerce.number().optional(),
  minute: z.coerce.number().optional(),

  partnerId: z.string().optional(),
  partnerName: z.string().optional(),
  codusur2: z.string().optional(),
  customerName: z.string().optional(),
  stockId: z.union([z.string(), z.array(z.string())]).optional(),
  sellerId: z.string().optional(),
  sellerName: z.string().optional(),

  customerId: z.coerce.number().optional(),
  billingId: z.string().optional(),
  orderId: z.coerce.number().optional(),
  invoiceId: z.coerce.number().optional(),
  productId: z.coerce.number().optional(),
  productName: z.string().optional(),

  createDateIni: z.string().optional(),
  createDateEnd: z.string().optional(),
  codusur2Name: z.string().optional(),
  invoiceDateIni: z.string().optional(),
  invoiceDateEnd: z.string().optional(),
  deliveryDate: z.string().optional(),

  shippimentId: z.coerce.number().optional(),
  deliveryType: z.string().optional(),
  status: z.string().optional(),
  type: z.string().optional(),

  onlyPendingTransfer: z.coerce.boolean().optional(),

  statusTransfer: z
    .enum(['Em Trânsito', 'Em Separação', 'Aguardando Separação', 'Concluída'])
    .optional(),

  markId: z.coerce.number().optional(),
  markName: z.string().optional(),

  hasPreBox: z.coerce.boolean().optional(),
  preBoxFilial: z.string().optional(),
  transferDestFilial: z.string().optional(),

  transferDateIni: z.string().optional(),
  transferDateEnd: z.string().optional(),

  includeCompletedDeliveries: z.coerce.boolean().optional(),
});

/**
 * Type for order search/filter parameters.
 * Represents the input parameters for searching orders (query params).
 */
export type OrderFilters = z.infer<typeof findOrdersSchema>;

/**
 * Verifica se um valor deve ser considerado vazio e removido dos parâmetros.
 *
 * @param {any} val - O valor a ser verificado
 * @returns {boolean} true se o valor é considerado vazio
 */
const isEmptyValue = (val: any): boolean => {
  return (
    val === null ||
    val === undefined ||
    val === '' ||
    (typeof val === 'boolean' && !val) ||
    (typeof val === 'number' && val === 0) ||
    (Array.isArray(val) && val.length === 0)
  );
};

/**
 * Formata um valor para string, convertendo arrays em strings separadas por vírgula.
 *
 * @param {any} val - O valor a ser formatado
 * @returns {string} O valor formatado como string
 */
const formatValueToString = (val: any): string => {
  return Array.isArray(val) ? val.join(',') : String(val);
};

/**
 * Schema que transforma OrderFilters em parâmetros de API limpos.
 * Remove valores vazios, transforma 'store' para 'codfilial', e formata valores.
 */
export const orderApiParamsSchema = findOrdersSchema
  .transform((filters) => {
    const {
      productName,
      partnerName,
      customerName,
      customerId,
      ...rest
    } = filters;

    const queryParams: any = { ...rest };

    if (customerId) queryParams.customerId = customerId;
    else if (customerName) queryParams.customerName = customerName;

    if (filters.partnerId) queryParams.partnerId = filters.partnerId;
    if (filters.productId) queryParams.productId = filters.productId;

    return queryParams;
  })
  .transform((filters) => {
    const keyMap: Record<string, string> = {
      store: 'codfilial',
    };

    return Object.entries(filters).reduce(
      (acc, [key, value]) => {
        if (isEmptyValue(value)) return acc;

        const apiKey = keyMap[key] ?? key;
        acc[apiKey] = formatValueToString(value);
        return acc;
      },
      {} as Record<string, string>
    );
  });
