"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateModelHook = generateModelHook;
const generator_1 = require("@postxl/generator");
function generateModelHook({ model, context }) {
    const { itemHook, itemsHook, trpcRoute } = model;
    const imports = generator_1.ImportGenerator
        //
        .from(model.itemHook.location)
        .addType(model.types)
        .addType(model.types.id)
        .addType(model.types.filter.type)
        .add(context.trpcClient)
        .addImports({
        [(0, generator_1.toPackageName)('@tanstack/react-query')]: [(0, generator_1.toFunctionName)('useQuery')],
    });
    let itemsCrudHook = { types: '', hooks: '', exports: '' };
    if (model.update.kind === 'exists') {
        imports
            .addType({ name: (0, generator_1.toTypeName)('CreatePayload'), location: model.update.service.location })
            .addType({ name: (0, generator_1.toTypeName)('UpdatePayload'), location: model.update.service.location })
            .addType({ name: (0, generator_1.toTypeName)('UpdateFieldPayload'), location: model.update.service.location })
            .addType({ name: (0, generator_1.toTypeName)('ClonePayload'), location: model.update.service.location })
            .addImports({
            [(0, generator_1.toPackageName)('@tanstack/react-query')]: [(0, generator_1.toFunctionName)('useMutation')],
            [(0, generator_1.toPackageName)('@lib/query-client')]: [(0, generator_1.toFunctionName)('queryClient')],
        });
        itemsCrudHook = {
            types: `
        ${itemsHook.update.name}: (data: UpdatePayload) => Promise<${model.types.name}>
        ${itemsHook.updateMany.name}: (data: UpdatePayload[]) => Promise<${model.types.name}[]>
        ${itemsHook.updateField.name}: (data: UpdateFieldPayload) => Promise<${model.types.name}>
        ${itemsHook.create.name}: (data: CreatePayload) => Promise<${model.types.name}>
        ${itemsHook.createMany.name}: (data: CreatePayload[]) => Promise<${model.types.name}[]>
        ${itemsHook.delete.name}: (id: ${model.types.id.name}) => Promise<${model.types.id.name}>
        ${itemsHook.deleteMany.name}: (ids: ${model.types.id.name}[]) => Promise<${model.types.id.name}[]>
        ${itemsHook.clone.name}: (data: ClonePayload) => Promise<${model.types.name}>
        ${itemsHook.cloneMany.name}: (data: ClonePayload[]) => Promise<${model.types.name}[]>`,
            hooks: `
        const invalidate = () => {
          void queryClient.invalidateQueries({ queryKey: trpc.${trpcRoute.name}.getMap.queryKey() })
          void queryClient.invalidateQueries({ queryKey: trpc.${trpcRoute.name}.getFiltered.queryKey() })
        }

        const updateMutation = useMutation(trpc.${trpcRoute.name}.update.mutationOptions({ onSuccess: invalidate }))
        const updateManyMutation = useMutation(trpc.${trpcRoute.name}.updateMany.mutationOptions({ onSuccess: invalidate }))
        const updateFieldMutation = useMutation(trpc.${trpcRoute.name}.updateField.mutationOptions({ onSuccess: invalidate }))
        const createMutation = useMutation(trpc.${trpcRoute.name}.create.mutationOptions({ onSuccess: invalidate }))
        const createManyMutation = useMutation(trpc.${trpcRoute.name}.createMany.mutationOptions({ onSuccess: invalidate }))
        const deleteMutation = useMutation(trpc.${trpcRoute.name}.delete.mutationOptions({ onSuccess: invalidate }))
        const deleteManyMutation = useMutation(trpc.${trpcRoute.name}.deleteMany.mutationOptions({ onSuccess: invalidate }))
        const cloneMutation = useMutation(trpc.${trpcRoute.name}.clone.mutationOptions({ onSuccess: invalidate }))
        const cloneManyMutation = useMutation(trpc.${trpcRoute.name}.cloneMany.mutationOptions({ onSuccess: invalidate }))
        `,
            exports: `
        ${itemsHook.update.name}: updateMutation.mutateAsync,
        ${itemsHook.updateMany.name}: updateManyMutation.mutateAsync,
        ${itemsHook.updateField.name}: updateFieldMutation.mutateAsync,
        ${itemsHook.create.name}: createMutation.mutateAsync,
        ${itemsHook.createMany.name}: createManyMutation.mutateAsync,
        ${itemsHook.delete.name}: deleteMutation.mutateAsync,
        ${itemsHook.deleteMany.name}: deleteManyMutation.mutateAsync,
        ${itemsHook.clone.name}: cloneMutation.mutateAsync,
        ${itemsHook.cloneMany.name}: cloneManyMutation.mutateAsync,`,
        };
    }
    return `
import { useMemo } from 'react'
${imports.generate()}

export type ${itemsHook.type.name} = {
  ${itemsHook.list.name}: ${model.types.name}[]
  ${itemsHook.map.name}: Map<${model.types.id.name}, ${model.types.name}>
  ${itemsHook.filteredList.name}: ${model.types.name}[]
  ${itemsHook.filteredMap.name}: Map<${model.types.id.name}, ${model.types.name}>
  ${itemsHook.isLoaded.name}: boolean

  ${itemsCrudHook.types}
}


export const ${itemHook.name} = (id: ${model.types.id.name} | null):  ${model.types.name} | null => {
  const trpc = ${context.trpcClient.name}()
    
  const { data, isPending } = useQuery(trpc.${trpcRoute.name}.get.queryOptions(id!, { enabled: id !== null })) // NOSONAR

  return useMemo((): ${model.types.name} | null => (isPending || !data) ? null : data, [data, isPending])
}

export const ${itemsHook.name} = (filters?: ${model.types.filter.type.name}): ${itemsHook.type.name} => {
  const trpc = ${context.trpcClient.name}()
  const isFiltered = useMemo(() => filters && Object.keys(filters).length > 0, [filters])

  const mapQuery = useQuery(trpc.${trpcRoute.name}.getMap.queryOptions())
  const filteredListQuery = useQuery({
    ...trpc.${trpcRoute.name}.getFiltered.queryOptions(filters ?? {}),
    enabled: !!isFiltered,
  })

  ${itemsCrudHook.hooks}

  const ${itemsHook.map.name} = useMemo((): Map<${model.types.id.name}, ${model.types.name}> => (mapQuery.isPending || !mapQuery.data) ? new Map() : mapQuery.data, [mapQuery.data, mapQuery.isPending])

  const ${itemsHook.list.name} = useMemo((): ${model.types.name}[] => Array.from(${itemsHook.map.name}.values()), [${itemsHook.map.name}])

  const ${itemsHook.filteredList.name} = useMemo((): ${model.types.name}[] => {
    if (isFiltered) {
      return filteredListQuery.data ?? []
    }
    return ${itemsHook.list.name}
  }, [isFiltered, filteredListQuery.data, ${itemsHook.list.name}])

  const ${itemsHook.filteredMap.name} = useMemo((): Map<${model.types.id.name}, ${model.types.name}> => {
    if (isFiltered) {
      return new Map(${itemsHook.filteredList.name}.map((i) => [i.${model.idField.name}, i]))
    }
    return ${itemsHook.map.name}
  }, [isFiltered, ${itemsHook.filteredList.name}, ${itemsHook.map.name}])

  return {
    ${itemsHook.list.name},
    ${itemsHook.map.name},
    ${itemsHook.filteredList.name},
    ${itemsHook.filteredMap.name},
    ${itemsHook.isLoaded.name}: !mapQuery.isPending && !mapQuery.isError,

    ${itemsCrudHook.exports}
  }
}`;
}
//# sourceMappingURL=model-hook.generator.js.map