import { useDataSource } from "@erp/core/hooks";
import { UniqueID, ValidationErrorCollection } from "@repo/rdx-ddd";
import { DefaultError, useMutation, useQueryClient } from "@tanstack/react-query";
import { ZodError } from "zod/v4";
import { CreateCustomerRequestSchema } from "../../common";
import { Customer, CustomerFormData } from "../schemas";
import { CUSTOMERS_LIST_KEY, invalidateCustomerListCache } from "./use-customer-list-query";
import { setCustomerDetailCache } from "./use-customer-query";

export const CUSTOMER_CREATE_KEY = ["customers", "create"] as const;

type CreateCustomerPayload = {
  data: CustomerFormData;
};

// Helpers de validación a errores de dominio
export function toValidationErrors(error: ZodError<unknown>) {
  return error.issues.map((err) => ({
    field: err.path.join("."),
    message: err.message,
  }));
}

export function useCreateCustomer() {
  const queryClient = useQueryClient();
  const dataSource = useDataSource();
  const schema = CreateCustomerRequestSchema;

  return useMutation<Customer, DefaultError, CreateCustomerPayload>({
    mutationKey: CUSTOMER_CREATE_KEY,

    mutationFn: async ({ data }, context) => {
      const id = UniqueID.generateNewID().toString();
      const payload = { ...data, id };

      const result = schema.safeParse(payload);

      if (!result.success) {
        throw new ValidationErrorCollection("Validation failed", toValidationErrors(result.error));
      }

      const created = await dataSource.createOne("customers", payload);
      return created as Customer;
    },

    onSuccess: (created: Customer, variables) => {
      const { id: customerId } = created;

      // Invalida el listado para refrescar desde servidor
      invalidateCustomerListCache(queryClient);

      // Sincroniza detalle
      setCustomerDetailCache(queryClient, customerId, created);
    },

    onSettled: () => {
      // Refresca todos los listados
      invalidateCustomerListCache(queryClient);
    },

    onMutate: async ({ data }, context) => {
      // Cancelar queries del listado para evitar overwrite
      await queryClient.cancelQueries({ queryKey: [CUSTOMERS_LIST_KEY] });

      const optimisticId = UniqueID.generateNewID().toString();
      const optimisticCustomer: Customer = { ...data, id: optimisticId } as Customer;

      // Snapshot previo
      const previous = queryClient.getQueryData<Customer[]>([CUSTOMERS_LIST_KEY]);

      // Optimista: prepend
      queryClient.setQueryData<Customer[]>([CUSTOMERS_LIST_KEY], (old) => [
        optimisticCustomer,
        ...(old ?? []),
      ]);

      return { previous, optimisticId };
    },
  });
}
