"use server";

import { redirect } from "next/navigation";

import { attachFindingTriageSummariesToResponse } from "@/actions/findings/findings-triage.adapter";
import { getFindingTriageAdapterOptions } from "@/actions/findings/findings-triage.options";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";

const withFindingTriageSummaries = <T extends { data?: unknown }>(
  response: T | undefined,
): T | undefined => {
  return attachFindingTriageSummariesToResponse(
    response,
    getFindingTriageAdapterOptions(),
  );
};

export const getFindings = async ({
  page = 1,
  pageSize = 10,
  query = "",
  sort = "",
  filters = {},
}) => {
  const headers = await getAuthHeaders({ contentType: false });

  if (isNaN(Number(page)) || page < 1)
    redirect("findings?include=resources,scan.provider");

  const url = new URL(`${apiBaseUrl}/findings?include=resources,scan.provider`);

  if (page) url.searchParams.append("page[number]", page.toString());
  if (pageSize) url.searchParams.append("page[size]", pageSize.toString());

  if (query) url.searchParams.append("filter[search]", query);
  if (sort) url.searchParams.append("sort", sort);

  appendSanitizedProviderTypeFilters(url, filters);

  try {
    const findings = await fetch(url.toString(), {
      headers,
    });
    const response = await handleApiResponse(findings);

    return withFindingTriageSummaries(response);
  } catch (error) {
    console.error("Error fetching findings:", error);
    return undefined;
  }
};

export const getLatestFindings = async ({
  page = 1,
  pageSize = 10,
  query = "",
  sort = "",
  filters = {},
}) => {
  const headers = await getAuthHeaders({ contentType: false });

  if (isNaN(Number(page)) || page < 1)
    redirect("findings?include=resources,scan.provider");

  const url = new URL(
    `${apiBaseUrl}/findings/latest?include=resources,scan.provider`,
  );

  if (page) url.searchParams.append("page[number]", page.toString());
  if (pageSize) url.searchParams.append("page[size]", pageSize.toString());

  if (query) url.searchParams.append("filter[search]", query);
  if (sort) url.searchParams.append("sort", sort);

  appendSanitizedProviderTypeFilters(url, filters);

  try {
    const findings = await fetch(url.toString(), {
      headers,
    });
    const response = await handleApiResponse(findings);

    return withFindingTriageSummaries(response);
  } catch (error) {
    console.error("Error fetching findings:", error);
    return undefined;
  }
};

export const getMetadataInfo = async ({
  query = "",
  sort = "",
  filters = {},
}) => {
  const headers = await getAuthHeaders({ contentType: false });

  const url = new URL(`${apiBaseUrl}/findings/metadata`);

  if (query) url.searchParams.append("filter[search]", query);
  if (sort) url.searchParams.append("sort", sort);

  appendSanitizedProviderTypeFilters(url, filters, {
    excludedKeyIncludes: [
      "region__in",
      "service__in",
      "resource_type__in",
      "resource_groups__in",
    ],
  });

  try {
    const response = await fetch(url.toString(), {
      headers,
    });

    return handleApiResponse(response);
  } catch (error) {
    console.error("Error fetching metadata info:", error);
    return undefined;
  }
};

export const getLatestMetadataInfo = async ({
  query = "",
  sort = "",
  filters = {},
}) => {
  const headers = await getAuthHeaders({ contentType: false });

  const url = new URL(`${apiBaseUrl}/findings/metadata/latest`);

  if (query) url.searchParams.append("filter[search]", query);
  if (sort) url.searchParams.append("sort", sort);

  appendSanitizedProviderTypeFilters(url, filters, {
    excludedKeyIncludes: [
      "region__in",
      "service__in",
      "resource_type__in",
      "resource_groups__in",
    ],
  });

  try {
    const response = await fetch(url.toString(), {
      headers,
    });

    return handleApiResponse(response);
  } catch (error) {
    console.error("Error fetching metadata info:", error);
    return undefined;
  }
};

interface GetFindingByIdOptions {
  source?: "resource-detail-drawer";
}

export const getFindingById = async (
  findingId: string,
  include = "",
  _options?: GetFindingByIdOptions,
) => {
  const headers = await getAuthHeaders({ contentType: false });

  const url = new URL(`${apiBaseUrl}/findings/${findingId}`);
  if (include) url.searchParams.append("include", include);

  try {
    const response = await fetch(url.toString(), {
      headers,
    });

    return handleApiResponse(response);
  } catch (error) {
    console.error("Error fetching finding by ID:", error);
    return undefined;
  }
};
