import { createQueryKeys } from '@lukemorales/query-key-factory';

import {
  getScanCompareApiClient,
  getScanResultCompletionApiClient,
  getSearchApiClient,
  getVulnerabilityApiClient,
} from '@/api/api';
import {
  CompletionCompletionNodeFieldReq,
  ModelNodeIdentifierNodeTypeEnum,
  ModelScanCompareReq,
  ModelScanInfo,
  ModelScanInfoStatusEnum,
  ModelScanResultsReq,
  ModelVulnerability,
  SearchSearchNodeReq,
  SearchSearchScanReq,
} from '@/api/generated';
import { DF404Error } from '@/components/error/404';
import { VulnerabilitiesCountsCardData } from '@/features/vulnerabilities/components/landing/VulnerabilitiesCountsCard';
import { getResponseErrors } from '@/utils/403';
import { apiWrapper } from '@/utils/api';
import { SeverityEnum } from '@/utils/enum';
import { SCAN_STATUS_FILTER_TYPE, SCAN_STATUS_GROUPS } from '@/utils/scan';

export const vulnerabilityQueries = createQueryKeys('vulnerability', {
  scanList: (filters: {
    page?: number;
    nodeTypes?: string[];
    order?: {
      sortBy: string;
      descending: boolean;
    };
    vulnerabilityScanStatus?: SCAN_STATUS_FILTER_TYPE;
    hosts?: string[];
    containers?: string[];
    images?: string[];
    languages?: string[];
    clusters?: string[];
    registryAccounts?: string[];
    pageSize: number;
  }) => {
    const {
      page = 1,
      nodeTypes = [],
      vulnerabilityScanStatus,
      hosts,
      containers,
      images,
      languages,
      clusters,
      pageSize,
      order,
      registryAccounts,
    } = filters;
    return {
      queryKey: [{ filters }],
      queryFn: async () => {
        type ScanResult = ModelScanInfo & {
          total: number;
          critical: number;
          high: number;
          medium: number;
          low: number;
          unknown: number;
        };
        const results: {
          scans: ScanResult[];
          currentPage: number;
          totalRows: number;
          message?: string;
        } = {
          scans: [],
          currentPage: 1,
          totalRows: 0,
        };

        const nodeFilters = {
          node_type: nodeTypes,
        } as {
          node_type?: string[];
          host_name?: string[];
          node_id?: string[];
          docker_image_id?: string[];
          vulnerability_scan_status?: string[];
        };
        if (hosts && hosts?.length > 0) {
          nodeFilters.host_name = nodeFilters.host_name
            ? nodeFilters.host_name.concat(hosts)
            : hosts;
        }
        if (containers && containers?.length > 0) {
          nodeFilters.node_id = nodeFilters.node_id
            ? nodeFilters.node_id.concat(containers)
            : containers;
        }
        if (images && images?.length > 0) {
          nodeFilters.docker_image_id = nodeFilters.docker_image_id
            ? nodeFilters.docker_image_id.concat(images)
            : images;
        }

        const languageFilters = {} as {
          trigger_action: string[];
        };
        if (languages && languages.length > 0) {
          languageFilters.trigger_action = languages.map((language) =>
            language.toLowerCase(),
          );
        }
        if (vulnerabilityScanStatus) {
          nodeFilters.vulnerability_scan_status =
            SCAN_STATUS_GROUPS[vulnerabilityScanStatus];
        }

        const scanRequestParams: SearchSearchScanReq = {
          node_filters: {
            filters: {
              match_filter: {
                filter_in: {
                  ...languageFilters,
                },
              },
              order_filter: { order_fields: [] },
              contains_filter: { filter_in: { ...nodeFilters } },
              compare_filter: null,
              not_contains_filter: {
                filter_in: {},
              },
            },
            in_field_filter: null,
            window: {
              offset: 0,
              size: 0,
            },
          },
          scan_filters: {
            filters: {
              match_filter: { filter_in: {} },
              order_filter: { order_fields: [] },
              contains_filter: { filter_in: {} },
              compare_filter: null,
              not_contains_filter: {
                filter_in: {},
              },
            },
            in_field_filter: null,
            window: {
              offset: 0,
              size: 1,
            },
          },
          window: { offset: page * pageSize, size: pageSize },
        };
        if (order) {
          scanRequestParams.scan_filters.filters.order_filter.order_fields = [
            {
              field_name: order.sortBy,
              descending: order.descending,
            },
          ];
        } else {
          scanRequestParams.scan_filters.filters.order_filter.order_fields = [
            {
              field_name: 'updated_at',
              descending: true,
            },
          ];
        }
        if (registryAccounts?.length) {
          scanRequestParams.related_node_filter = {
            relation_ship: 'HOSTS',
            node_filter: {
              filters: {
                compare_filter: null,
                contains_filter: {
                  filter_in: {
                    node_id: registryAccounts,
                  },
                },
                match_filter: {
                  filter_in: {},
                },
                not_contains_filter: {
                  filter_in: {},
                },
                order_filter: {
                  order_fields: [],
                },
              },
              in_field_filter: null,
              window: {
                offset: 0,
                size: 0,
              },
            },
          };
        }

        if (clusters && clusters?.length > 0) {
          if (scanRequestParams.related_node_filter) {
            scanRequestParams.related_node_filter.next_filter = {
              relation_ship: 'INSTANCIATE',
              node_filter: {
                filters: {
                  compare_filter: null,
                  contains_filter: {
                    filter_in: {
                      node_id: clusters,
                    },
                  },
                  match_filter: {
                    filter_in: {},
                  },
                  not_contains_filter: {
                    filter_in: {},
                  },
                  order_filter: {
                    order_fields: [],
                  },
                },
                in_field_filter: null,
                window: {
                  offset: 0,
                  size: 0,
                },
              },
            };
          } else {
            scanRequestParams.related_node_filter = {
              relation_ship: 'HOSTS',
              node_filter: {
                filters: {
                  compare_filter: null,
                  contains_filter: {
                    filter_in: {},
                  },
                  match_filter: {
                    filter_in: {},
                  },
                  not_contains_filter: {
                    filter_in: {},
                  },
                  order_filter: {
                    order_fields: [],
                  },
                },
                in_field_filter: null,
                window: {
                  offset: 0,
                  size: 0,
                },
              },
              next_filter: {
                relation_ship: 'INSTANCIATE',
                node_filter: {
                  filters: {
                    compare_filter: null,
                    contains_filter: {
                      filter_in: {
                        node_id: clusters,
                      },
                    },
                    match_filter: {
                      filter_in: {},
                    },
                    not_contains_filter: {
                      filter_in: {},
                    },
                    order_filter: {
                      order_fields: [],
                    },
                  },
                  in_field_filter: null,
                  window: {
                    offset: 0,
                    size: 0,
                  },
                },
              },
            };
          }
        }

        const searchVulnerabilityScanApi = apiWrapper({
          fn: getSearchApiClient().searchVulnerabilityScan,
        });
        const resultPromise = searchVulnerabilityScanApi({
          searchSearchScanReq: scanRequestParams,
        });

        const countsResultApi = apiWrapper({
          fn: getSearchApiClient().searchVulnerabilityScanCount,
        });
        const countsResultPromise = countsResultApi({
          searchSearchScanReq: {
            ...scanRequestParams,
            window: {
              ...scanRequestParams.window,
              size: 10 * scanRequestParams.window.size,
            },
          },
        });
        const [result, countsResult] = await Promise.all([
          resultPromise,
          countsResultPromise,
        ]);
        if (!result.ok) {
          throw result.error;
        }
        if (!countsResult.ok) {
          throw countsResult.error;
        }

        if (result.value === null) {
          return results;
        }

        results.scans = result.value.map((scan) => {
          const severities = scan.severity_counts as {
            critical: number;
            high: number;
            medium: number;
            low: number;
            unknown: number;
          };
          severities.critical = severities.critical ?? 0;
          severities.high = severities.high ?? 0;
          severities.medium = severities.medium ?? 0;
          severities.low = severities.low ?? 0;
          severities.unknown = severities.unknown ?? 0;

          return {
            ...scan,
            total:
              severities.critical +
              severities.high +
              severities.medium +
              severities.low +
              severities.unknown,
            critical: severities.critical,
            high: severities.high,
            medium: severities.medium,
            low: severities.low,
            unknown: severities.unknown,
          };
        });

        results.currentPage = page;
        results.totalRows = page * pageSize + countsResult.value.count;

        return results;
      },
    };
  },
  scanResults: (filters: {
    scanId: string;
    page: number;
    pageSize: number;
    severity: string[];
    cve: string[];
    language: string[];
    attackVector: string[];
    visibility: string[];
    order?: {
      sortBy: string;
      descending: boolean;
    };
    exploitable?: string[];
  }) => {
    return {
      queryKey: [{ filters }],
      queryFn: async () => {
        const {
          scanId,
          visibility,
          severity,
          cve,
          language,
          attackVector,
          page,
          order,
          pageSize,
          exploitable,
        } = filters;
        // status api
        const statusVulnerabilityScanApi = apiWrapper({
          fn: getVulnerabilityApiClient().statusVulnerabilityScan,
        });
        const searchVulnerabilitiesResponse = await statusVulnerabilityScanApi({
          modelScanStatusReq: {
            scan_ids: [scanId],
            bulk_scan_id: '',
          },
        });
        if (!searchVulnerabilitiesResponse.ok) {
          if (searchVulnerabilitiesResponse.error.response.status === 400) {
            const { message } = await getResponseErrors(
              searchVulnerabilitiesResponse.error,
            );
            return { message };
          } else if (searchVulnerabilitiesResponse.error.response.status === 404) {
            throw new DF404Error('Scan not found');
          }
          throw searchVulnerabilitiesResponse.error;
        }

        if (
          !searchVulnerabilitiesResponse ||
          !searchVulnerabilitiesResponse.value?.statuses?.[scanId]
        ) {
          throw new Error('Scan status not found');
        }

        const scanStatus = searchVulnerabilitiesResponse.value?.statuses?.[scanId].status;

        const isScanRunning =
          scanStatus !== ModelScanInfoStatusEnum.Complete &&
          scanStatus !== ModelScanInfoStatusEnum.Error;
        const isScanError = scanStatus === ModelScanInfoStatusEnum.Error;

        if (isScanRunning || isScanError) {
          return {
            scanStatusResult: searchVulnerabilitiesResponse.value.statuses[scanId],
          };
        }

        const scanResultsReq: ModelScanResultsReq = {
          fields_filter: {
            contains_filter: {
              filter_in: {},
            },
            match_filter: { filter_in: {} },
            order_filter: { order_fields: [] },
            compare_filter: null,
          },
          scan_id: scanId,
          window: {
            offset: page * pageSize,
            size: pageSize,
          },
        };

        if (exploitable && exploitable.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in![
            'exploitability_score'
          ] = [1, 2, 3];
        }

        if (cve.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['cve_id'] = cve;
        }

        if (language.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['cve_type'] = language;
        }

        if (attackVector.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in![
            'parsed_attack_vector'
          ] = attackVector;
        }

        if (severity.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['cve_severity'] =
            severity;
        }

        if (visibility.length === 1) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['masked'] = [
            visibility.includes('masked') ? true : false,
          ];
        }

        if (order) {
          scanResultsReq.fields_filter.order_filter.order_fields?.push({
            field_name: order.sortBy,
            descending: order.descending,
          });
        }

        const resultVulnerabilityScanApi = apiWrapper({
          fn: getVulnerabilityApiClient().resultVulnerabilityScan,
        });
        const resultVulnerabilityScanPromise = resultVulnerabilityScanApi({
          modelScanResultsReq: scanResultsReq,
        });

        const resultCountVulnerabilityScanApi = apiWrapper({
          fn: getVulnerabilityApiClient().resultCountVulnerabilityScan,
        });
        const resultCountsPromise = resultCountVulnerabilityScanApi({
          modelScanResultsReq: {
            ...scanResultsReq,
            window: {
              ...scanResultsReq.window,
              size: 10 * scanResultsReq.window.size,
            },
          },
        });

        const [resultVulnerabilityScanResponse, resultCounts] = await Promise.all([
          resultVulnerabilityScanPromise,
          resultCountsPromise,
        ]);

        if (!resultVulnerabilityScanResponse.ok) {
          throw resultVulnerabilityScanResponse.error;
        }

        if (resultVulnerabilityScanResponse.value === null) {
          throw new Error('Error getting scan results');
        }
        const totalSeverity = Object.values(
          resultVulnerabilityScanResponse.value.severity_counts ?? {},
        ).reduce((acc, value) => {
          acc = acc + value;
          return acc;
        }, 0);

        if (!resultCounts.ok) {
          throw resultCounts.error;
        }

        return {
          scanStatusResult: searchVulnerabilitiesResponse.value.statuses[scanId],
          data: {
            totalSeverity,
            severityCounts: {
              critical:
                resultVulnerabilityScanResponse.value.severity_counts?.[
                  SeverityEnum.Critical
                ] ?? 0,
              high:
                resultVulnerabilityScanResponse.value.severity_counts?.[
                  SeverityEnum.High
                ] ?? 0,
              medium:
                resultVulnerabilityScanResponse.value.severity_counts?.[
                  SeverityEnum.Medium
                ] ?? 0,
              low:
                resultVulnerabilityScanResponse.value.severity_counts?.[
                  SeverityEnum.Low
                ] ?? 0,
              unknown:
                resultVulnerabilityScanResponse.value.severity_counts?.[
                  SeverityEnum.Unknown
                ] ?? 0,
            },
            timestamp: resultVulnerabilityScanResponse.value.updated_at,
            tableData: resultVulnerabilityScanResponse.value.vulnerabilities ?? [],
            dockerImageName: resultVulnerabilityScanResponse.value.docker_image_name,
            pagination: {
              currentPage: page,
              totalRows: page * pageSize + resultCounts.value.count,
            },
          },
        };
      },
    };
  },
  top5VulnerabilitiesForScan: (filters: {
    scanId: string;
    severity: string[];
    cve: string[];
    language: string[];
    attackVector: string[];
    visibility: string[];
    exploitable?: string[];
  }) => {
    return {
      queryKey: [{ filters }],
      queryFn: async () => {
        const { scanId, severity, cve, language, attackVector, visibility, exploitable } =
          filters;

        const scanResultsReq: ModelScanResultsReq = {
          fields_filter: {
            contains_filter: {
              filter_in: {},
            },
            match_filter: { filter_in: {} },
            order_filter: {
              order_fields: [
                {
                  field_name: 'cve_cvss_score',
                  descending: true,
                },
              ],
            },
            compare_filter: null,
          },
          scan_id: scanId,
          window: {
            offset: 0,
            size: 5,
          },
        };

        if (exploitable && exploitable.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in![
            'exploitability_score'
          ] = [1, 2, 3];
        }

        if (cve.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['cve_id'] = cve;
        }

        if (language.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['cve_type'] = language;
        }

        if (attackVector.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in![
            'parsed_attack_vector'
          ] = attackVector;
        }

        if (severity.length) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['cve_severity'] =
            severity;
        }

        if (visibility.length === 1) {
          scanResultsReq.fields_filter.contains_filter.filter_in!['masked'] = [
            visibility.includes('masked') ? true : false,
          ];
        }

        const resultVulnerabilityScanApi = apiWrapper({
          fn: getVulnerabilityApiClient().resultVulnerabilityScan,
        });
        const resultVulnerabilityScanResponse = await resultVulnerabilityScanApi({
          modelScanResultsReq: scanResultsReq,
        });

        if (!resultVulnerabilityScanResponse.ok) {
          if (resultVulnerabilityScanResponse.error.response.status === 404) {
            throw new DF404Error('Scan not found');
          }
          throw resultVulnerabilityScanResponse.error;
        }

        if (resultVulnerabilityScanResponse.value === null) {
          throw new Error('Error getting scan results');
        }

        return {
          data: resultVulnerabilityScanResponse.value.vulnerabilities,
        };
      },
    };
  },
  uniqueVulnerabilities: (filters: {
    page?: number;
    order?: {
      sortBy: string;
      descending: boolean;
    };
    pageSize: number;
    severity: string[];
    liveConnection: string[];
    hostIds: string[];
    containerIds: string[];
    containerImageIds: string[];
    clusterIds: string[];
    cve: string[];
  }) => {
    const {
      page = 1,
      order,
      severity,
      liveConnection,
      pageSize,
      hostIds,
      containerIds,
      containerImageIds,
      clusterIds,
      cve,
    } = filters;
    return {
      queryKey: [{ filters }],
      queryFn: async () => {
        const results: {
          vulnerabilities: Array<ModelVulnerability>;
          currentPage: number;
          totalRows: number;
          message?: string;
        } = {
          currentPage: 1,
          totalRows: 0,
          vulnerabilities: [],
        };

        const searchVulnerabilitiesRequestParams: SearchSearchNodeReq = {
          node_filter: {
            filters: {
              contains_filter: { filter_in: {} },
              order_filter: { order_fields: [] },
              match_filter: { filter_in: {} },
              compare_filter: null,
            },
            in_field_filter: null,
            window: {
              offset: 0,
              size: 0,
            },
          },
          window: { offset: page * pageSize, size: pageSize },
        };
        const nodeIds = [...hostIds, ...containerIds, ...containerImageIds];

        if (nodeIds.length || clusterIds.length) {
          const nodeTypes = [];
          if (hostIds.length) {
            nodeTypes.push('host');
          }
          if (containerIds.length) {
            nodeTypes.push('container');
          }
          if (containerImageIds.length) {
            nodeTypes.push('container_image');
          }

          const containsFilter = {
            filter_in: {},
          };
          if (nodeIds.length) {
            containsFilter.filter_in = {
              node_id: nodeIds,
              node_type: nodeTypes,
            };
          }
          if (clusterIds.length) {
            containsFilter.filter_in = {
              ...containsFilter.filter_in,
              kubernetes_cluster_id: clusterIds,
            };
          }
          searchVulnerabilitiesRequestParams.related_node_filter = {
            relation_ship: 'DETECTED',
            node_filter: {
              filters: {
                contains_filter: { filter_in: {} },
                order_filter: { order_fields: [] },
                match_filter: { filter_in: {} },
                compare_filter: null,
              },
              in_field_filter: null,
              window: {
                offset: 0,
                size: 0,
              },
            },
            next_filter: {
              relation_ship: 'SCANNED',
              node_filter: {
                filters: {
                  contains_filter: containsFilter,
                  compare_filter: [],
                  match_filter: { filter_in: {} },
                  order_filter: { order_fields: [] },
                },
                in_field_filter: [],
                window: {
                  offset: 0,
                  size: 0,
                },
              },
            },
          };
        }

        if (severity.length) {
          searchVulnerabilitiesRequestParams.node_filter.filters.contains_filter.filter_in![
            'cve_severity'
          ] = severity;
        }
        if (liveConnection.length) {
          if (liveConnection.length === 1) {
            searchVulnerabilitiesRequestParams.node_filter.filters.contains_filter.filter_in![
              'has_live_connection'
            ] = [liveConnection[0] === 'active'];
          }
        }

        if (cve.length) {
          searchVulnerabilitiesRequestParams.node_filter.filters.contains_filter.filter_in![
            'cve_id'
          ] = cve;
        }

        if (order) {
          searchVulnerabilitiesRequestParams.node_filter.filters.order_filter.order_fields =
            [
              {
                field_name: order.sortBy,
                descending: order.descending,
              },
            ];
        }

        const searchVulnerabilitiesApi = apiWrapper({
          fn: getSearchApiClient().searchVulnerabilities,
        });
        const searchVulnerabilitiesPromise = searchVulnerabilitiesApi({
          searchSearchNodeReq: searchVulnerabilitiesRequestParams,
        });

        const searchVulnerabilitiesCountApi = apiWrapper({
          fn: getSearchApiClient().searchVulnerabilitiesCount,
        });
        const searchVulnerabilitiesCountPromise = searchVulnerabilitiesCountApi({
          searchSearchNodeReq: {
            ...searchVulnerabilitiesRequestParams,
            window: {
              ...searchVulnerabilitiesRequestParams.window,
              size: 10 * pageSize,
            },
          },
        });
        const [searchVulnerabilitiesResponse, searchVulnerabilitiesCountResponse] =
          await Promise.all([
            searchVulnerabilitiesPromise,
            searchVulnerabilitiesCountPromise,
          ]);

        if (!searchVulnerabilitiesResponse.ok) {
          throw searchVulnerabilitiesResponse.error;
        }
        if (!searchVulnerabilitiesCountResponse.ok) {
          throw searchVulnerabilitiesCountResponse.error;
        }

        results.vulnerabilities = searchVulnerabilitiesResponse.value;
        results.currentPage = page;
        results.totalRows =
          page * pageSize + searchVulnerabilitiesCountResponse.value.count;

        return results;
      },
    };
  },
  top5VulnerableAssets: (filters: { nodeType: 'image' | 'host' | 'container' }) => {
    const { nodeType } = filters;
    return {
      queryKey: [filters],
      queryFn: async () => {
        const top5NodesApi = apiWrapper({
          fn: {
            [ModelNodeIdentifierNodeTypeEnum.Image]:
              getSearchApiClient().searchContainerImages,
            [ModelNodeIdentifierNodeTypeEnum.Host]: getSearchApiClient().searchHosts,
            [ModelNodeIdentifierNodeTypeEnum.Container]:
              getSearchApiClient().searchContainers,
          }[nodeType],
        });
        const top5Nodes = await top5NodesApi({
          searchSearchNodeReq: {
            node_filter: {
              filters: {
                contains_filter: {
                  filter_in: {
                    pseudo: [false],
                    active: [true],
                    vulnerability_scan_status: ['COMPLETE'],
                  },
                },
                match_filter: {
                  filter_in: {},
                },
                order_filter: {
                  order_fields: [
                    {
                      field_name: 'vulnerabilities_count',
                      descending: true,
                    },
                  ],
                },
                compare_filter: [
                  {
                    field_name: 'vulnerabilities_count',
                    field_value: 0,
                    greater_than: true,
                  },
                ],
              },
              in_field_filter: [],
              window: {
                offset: 0,
                size: 0,
              },
            },
            window: {
              offset: 0,
              size: 5,
            },
          },
        });
        if (!top5Nodes.ok) {
          throw new Error('error getting top 5 container images');
        }

        const top5NodeScansApi = apiWrapper({
          fn: getSearchApiClient().searchVulnerabilityScan,
        });
        const top5NodeScans = await top5NodeScansApi({
          searchSearchScanReq: {
            node_filters: {
              filters: {
                compare_filter: [],
                contains_filter: { filter_in: {} },
                match_filter: { filter_in: {} },
                order_filter: { order_fields: [] },
                not_contains_filter: { filter_in: {} },
              },
              in_field_filter: [],
              window: { offset: 0, size: 0 },
            },
            scan_filters: {
              filters: {
                compare_filter: [],
                contains_filter: {
                  filter_in: {
                    node_id: top5Nodes.value
                      .map((node) => node.vulnerability_latest_scan_id)
                      .filter((scanId) => {
                        return !!scanId?.length;
                      }),
                  },
                },
                match_filter: { filter_in: {} },
                order_filter: { order_fields: [] },
                not_contains_filter: { filter_in: {} },
              },
              in_field_filter: [],
              window: { offset: 0, size: 0 },
            },
            window: {
              offset: 0,
              size: 5,
            },
          },
        });

        if (!top5NodeScans.ok) {
          throw new Error('error getting top 5 scans');
        }

        return top5Nodes.value
          .map((node) => {
            const latestScan = top5NodeScans.value.find(
              (scan) => scan.node_id === node.node_id,
            );
            if (!latestScan) {
              return null;
            }
            return {
              name: latestScan.node_name,
              id: latestScan.node_id,
              critical: latestScan.severity_counts?.critical ?? 0,
              high: latestScan.severity_counts?.high ?? 0,
              medium: latestScan.severity_counts?.medium ?? 0,
              low: latestScan.severity_counts?.low ?? 0,
              unknown: latestScan.severity_counts?.unknown ?? 0,
            };
          })
          .reduce<
            Array<{
              name: string;
              critical: number;
              high: number;
              medium: number;
              low: number;
              unknown: number;
            }>
          >((acc, curr) => {
            if (curr) {
              acc.push(curr);
            }
            return acc;
          }, []);
      },
    };
  },
  mostExploitableVulnerabilitiesCount: () => {
    return {
      queryKey: ['mostExploitableVulnerabilitiesCount'],
      queryFn: async () => {
        const defaultResults: VulnerabilitiesCountsCardData = {
          total: 0,
          severityBreakdown: {
            critical: 0,
            high: 0,
            medium: 0,
            low: 0,
            unknown: 0,
          },
        };

        const searchVulnerabilitiesCountApi = apiWrapper({
          fn: getSearchApiClient().searchVulnerabilitiesCount,
        });
        const mostExploitableVulenrabilityCounts = await searchVulnerabilitiesCountApi({
          searchSearchNodeReq: {
            extended_node_filter: {
              in_field_filter: null,
              filters: {
                order_filter: {
                  order_fields: [{ descending: true, field_name: 'cve_cvss_score' }],
                },
                compare_filter: null,
                contains_filter: { filter_in: {} },
                match_filter: { filter_in: {} },
                not_contains_filter: { filter_in: {} },
              },
              window: {
                offset: 0,
                size: 0,
              },
            },
            node_filter: {
              filters: {
                contains_filter: { filter_in: { exploitability_score: [1, 2, 3] } },
                match_filter: { filter_in: {} },
                order_filter: {
                  order_fields: [
                    {
                      size: 1000,
                      field_name: 'exploitability_score',
                      descending: true,
                    },
                  ],
                },
                compare_filter: null,
              },
              in_field_filter: [],
              window: {
                offset: 0,
                size: 0,
              },
            },
            window: {
              offset: 0,
              size: 1000,
            },
          },
        });
        if (!mostExploitableVulenrabilityCounts.ok) {
          throw new Error('Error getting most exploitable count');
        }

        return {
          total: mostExploitableVulenrabilityCounts.value.count,
          severityBreakdown: {
            critical:
              mostExploitableVulenrabilityCounts.value.categories?.[
                SeverityEnum.Critical
              ] ?? 0,
            high:
              mostExploitableVulenrabilityCounts.value.categories?.[SeverityEnum.High] ??
              0,
            medium:
              mostExploitableVulenrabilityCounts.value.categories?.[
                SeverityEnum.Medium
              ] ?? 0,
            low:
              mostExploitableVulenrabilityCounts.value.categories?.[SeverityEnum.Low] ??
              0,
            unknown:
              mostExploitableVulenrabilityCounts.value.categories?.[
                SeverityEnum.Unknown
              ] ?? 0,
          },
        };
      },
    };
  },
  uniqueVulnerabilitiesCount: () => {
    return {
      queryKey: ['uniqueVulnerabilitiesCount'],
      queryFn: async () => {
        const defaultResults: VulnerabilitiesCountsCardData = {
          total: 0,
          severityBreakdown: {
            critical: 0,
            high: 0,
            medium: 0,
            low: 0,
            unknown: 0,
          },
        };
        const searchVulnerabilitiesCountApi = apiWrapper({
          fn: getSearchApiClient().searchVulnerabilitiesCount,
        });
        const uniqueVulenrabilityCounts = await searchVulnerabilitiesCountApi({
          searchSearchNodeReq: {
            node_filter: {
              filters: {
                contains_filter: { filter_in: {} },
                match_filter: { filter_in: {} },
                order_filter: { order_fields: [] },
                compare_filter: null,
              },
              in_field_filter: [],
              window: {
                offset: 0,
                size: 0,
              },
            },
            window: {
              offset: 0,
              size: 999999999,
            },
          },
        });

        if (!uniqueVulenrabilityCounts.ok) {
          throw new Error('Error getting unique vulnerability count');
        }

        return {
          total: uniqueVulenrabilityCounts.value.count,
          severityBreakdown: {
            critical:
              uniqueVulenrabilityCounts.value.categories?.[SeverityEnum.Critical] ?? 0,
            high: uniqueVulenrabilityCounts.value.categories?.[SeverityEnum.High] ?? 0,
            medium:
              uniqueVulenrabilityCounts.value.categories?.[SeverityEnum.Medium] ?? 0,
            low: uniqueVulenrabilityCounts.value.categories?.[SeverityEnum.Low] ?? 0,
            unknown:
              uniqueVulenrabilityCounts.value.categories?.[SeverityEnum.Unknown] ?? 0,
          },
        };
      },
    };
  },
  scanResultSummaryCounts: (filters: { scanId: string }) => {
    return {
      queryKey: [filters],
      queryFn: async () => {
        const { scanId } = filters;
        const resultVulnerabilityScanApi = apiWrapper({
          fn: getVulnerabilityApiClient().resultVulnerabilityScan,
        });
        const vulnerabilityScanResults = await resultVulnerabilityScanApi({
          modelScanResultsReq: {
            scan_id: scanId,
            window: {
              offset: 0,
              size: 1,
            },
            fields_filter: {
              contains_filter: {
                filter_in: {},
              },
              match_filter: {
                filter_in: {},
              },
              order_filter: { order_fields: [] },
              compare_filter: null,
            },
          },
        });

        if (!vulnerabilityScanResults.ok) {
          console.error(vulnerabilityScanResults);
          throw new Error("Couldn't get vulnerability scan results");
        }
        return {
          scanId,
          timestamp: vulnerabilityScanResults.value.created_at,
          counts: vulnerabilityScanResults.value.severity_counts ?? {},
        };
      },
    };
  },
  sbomForScan: (filters: { scanId: string }) => {
    return {
      queryKey: [filters],
      queryFn: async () => {
        const { scanId } = filters;
        if (!scanId) {
          throw new Error('ScanId is required');
        }
        const sbomDataApi = apiWrapper({
          fn: getVulnerabilityApiClient().getSbom,
        });
        const sbomResponse = await sbomDataApi({
          modelSbomRequest: {
            scan_id: scanId,
          },
        });
        if (!sbomResponse.ok) {
          if (sbomResponse.error.response.status >= 500) {
            return {
              sbom: [],
              message: 'Error getting SBOM data',
            };
          }
          throw sbomResponse.error;
        }

        return {
          sbom: sbomResponse.value,
        };
      },
    };
  },
  scanDiff: (filters: { baseScanId: string; toScanId: string }) => {
    const { baseScanId, toScanId } = filters;
    return {
      queryKey: [{ filters }],
      queryFn: async () => {
        if (!baseScanId || !toScanId) {
          throw new Error('Scan ids are required for comparision');
        }

        const results: {
          added: ModelVulnerability[];
          deleted: ModelVulnerability[];
          message?: string;
        } = {
          added: [],
          deleted: [],
        };

        const compareScansApi = apiWrapper({
          fn: getScanCompareApiClient().diffVulnerability,
        });

        const addedCompareReq: ModelScanCompareReq = {
          fields_filter: {
            contains_filter: {
              filter_in: {},
            },
            match_filter: { filter_in: {} },
            order_filter: { order_fields: [] },
            compare_filter: null,
          },
          base_scan_id: toScanId,
          to_scan_id: baseScanId,
          window: {
            offset: 0,
            size: 99999,
          },
        };

        const addScanPromise = compareScansApi({
          modelScanCompareReq: addedCompareReq,
        });

        // deleted
        const deletedCompareReq: ModelScanCompareReq = {
          fields_filter: {
            contains_filter: {
              filter_in: {},
            },
            match_filter: { filter_in: {} },
            order_filter: { order_fields: [] },
            compare_filter: null,
          },
          base_scan_id: baseScanId,
          to_scan_id: toScanId,
          window: {
            offset: 0,
            size: 99999,
          },
        };
        const deletedScanPromise = compareScansApi({
          modelScanCompareReq: deletedCompareReq,
        });

        const [addScanResponse, deletedScanResponse] = await Promise.all([
          addScanPromise,
          deletedScanPromise,
        ]);

        if (!addScanResponse.ok) {
          const { message } = await getResponseErrors(addScanResponse.error);
          return {
            error: 'Error getting scan diff',
            message,
            ...results,
          };
        }

        if (!addScanResponse.value) {
          return results;
        }

        const addedScans = addScanResponse.value._new;
        if (!deletedScanResponse.ok) {
          const { message } = await getResponseErrors(deletedScanResponse.error);
          return {
            error: 'Error getting scan diff',
            message,
            ...results,
          };
        }

        if (!deletedScanResponse.value) {
          return results;
        }
        const deletedScans = deletedScanResponse.value._new;

        results.added = addedScans ?? [];
        results.deleted = deletedScans ?? [];

        return results;
      },
    };
  },
  searchScanResultFilters: (filters: {
    scanId: string;
    fieldName: string;
    searchText: string;
    size: number;
  }) => {
    return {
      queryKey: [{ filters }],
      queryFn: async ({ pageParam = 0 }) => {
        const { scanId, fieldName, searchText, size } = filters;

        const scanResultsReq: CompletionCompletionNodeFieldReq = {
          completion: searchText,
          field_name: fieldName,
          scan_id: scanId,
          window: {
            offset: pageParam,
            size,
          },
        };

        const api = apiWrapper({
          fn: getScanResultCompletionApiClient().completeVulnerabilityInfo,
        });
        const response = await api({
          completionCompletionNodeFieldReq: scanResultsReq,
        });

        if (!response.ok) {
          throw response.error;
        }

        if (response.value === null) {
          throw new Error('Error getting scan results filters');
        }

        return {
          data: response.value.possible_values?.slice(0, size) || [],
        };
      },
    };
  },
});
