import { authApi, handleApiError } from "@/main-axios";

export interface NetworkTopologyNode {
  data: {
    id: string;
    label?: string;
    ip?: string;
    status?: string;
    tags?: string[];
    parent?: string;
    color?: string;
    /** Absent on nodes; callers tell nodes from edges by testing these. */
    source?: undefined;
    target?: undefined;
  };
  position?: { x: number; y: number };
}

export interface NetworkTopologyEdge {
  data: {
    id?: string;
    source: string;
    target: string;
    label?: undefined;
    ip?: undefined;
  };
}

export interface NetworkTopologyData {
  nodes: NetworkTopologyNode[];
  edges: NetworkTopologyEdge[];
}

/**
 * A snippet row as the list endpoint returns it. Callers that need the full
 * shape narrow it themselves; only the id is relied on across the app.
 */
export interface SnippetRow {
  id: number;
  [key: string]: unknown;
}

export async function getSnippets(): Promise<SnippetRow[]> {
  try {
    const response = await authApi.get("/snippets");
    return response.data;
  } catch (error) {
    throw handleApiError(error, "fetch snippets");
  }
}

export async function createSnippet(
  snippetData: Record<string, unknown>,
): Promise<Record<string, unknown>> {
  try {
    const response = await authApi.post("/snippets", snippetData);
    return response.data;
  } catch (error) {
    throw handleApiError(error, "create snippet");
  }
}

export async function updateSnippet(
  snippetId: number,
  snippetData: Record<string, unknown>,
): Promise<Record<string, unknown>> {
  try {
    const response = await authApi.put(`/snippets/${snippetId}`, snippetData);
    return response.data;
  } catch (error) {
    throw handleApiError(error, "update snippet");
  }
}

export async function deleteSnippet(
  snippetId: number,
): Promise<Record<string, unknown>> {
  try {
    const response = await authApi.delete(`/snippets/${snippetId}`);
    return response.data;
  } catch (error) {
    throw handleApiError(error, "delete snippet");
  }
}

export async function executeSnippet(
  snippetId: number,
  hostId: number,
  inputValues?: Record<string, string>,
): Promise<{ success: boolean; output: string; error?: string }> {
  try {
    const response = await authApi.post("/snippets/execute", {
      snippetId,
      hostId,
      ...(inputValues ? { inputValues } : {}),
    });
    return response.data;
  } catch (error) {
    throw handleApiError(error, "execute snippet");
  }
}

export async function getNetworkTopology(): Promise<NetworkTopologyData | null> {
  try {
    const response = await authApi.get("/network-topology/");
    return response.data;
  } catch (error) {
    throw handleApiError(error, "fetch network topology");
  }
}

export async function saveNetworkTopology(
  topology: NetworkTopologyData,
): Promise<{ success: boolean }> {
  try {
    const response = await authApi.post("/network-topology/", { topology });
    return response.data;
  } catch (error) {
    throw handleApiError(error, "save network topology");
  }
}

export async function getSnippetFolders(): Promise<Record<string, unknown>> {
  try {
    const response = await authApi.get("/snippets/folders");
    return response.data;
  } catch (error) {
    throw handleApiError(error, "fetch snippet folders");
  }
}

export async function createSnippetFolder(folderData: {
  name: string;
  color?: string;
  icon?: string;
}): Promise<Record<string, unknown>> {
  try {
    const response = await authApi.post("/snippets/folders", folderData);
    return response.data;
  } catch (error) {
    throw handleApiError(error, "create snippet folder");
  }
}

export async function updateSnippetFolderMetadata(
  folderName: string,
  metadata: { color?: string; icon?: string },
): Promise<Record<string, unknown>> {
  try {
    const response = await authApi.put(
      `/snippets/folders/${encodeURIComponent(folderName)}/metadata`,
      metadata,
    );
    return response.data;
  } catch (error) {
    throw handleApiError(error, "update snippet folder metadata");
  }
}

export async function renameSnippetFolder(
  oldName: string,
  newName: string,
): Promise<{ success: boolean; oldName: string; newName: string }> {
  try {
    const response = await authApi.put("/snippets/folders/rename", {
      oldName,
      newName,
    });
    return response.data;
  } catch (error) {
    throw handleApiError(error, "rename snippet folder");
  }
}

export async function deleteSnippetFolder(
  folderName: string,
): Promise<{ success: boolean }> {
  try {
    const response = await authApi.delete(
      `/snippets/folders/${encodeURIComponent(folderName)}`,
    );
    return response.data;
  } catch (error) {
    throw handleApiError(error, "delete snippet folder");
  }
}

export async function reorderSnippets(
  updates: Array<{ id: number; order: number; folder?: string }>,
): Promise<{ success: boolean }> {
  try {
    const response = await authApi.put("/snippets/reorder", {
      snippets: updates,
    });
    return response.data;
  } catch (error) {
    throw handleApiError(error, "reorder snippets");
  }
}

export interface SnippetExportData {
  snippets: Array<{
    name: string;
    content: string;
    description?: string | null;
    folder?: string | null;
    order?: number;
    hostFilter?: string | null;
  }>;
  folders: Array<{
    name: string;
    color?: string | null;
    icon?: string | null;
  }>;
}

export async function exportSnippets(): Promise<SnippetExportData> {
  try {
    const response = await authApi.get("/snippets/export");
    return response.data;
  } catch (error) {
    throw handleApiError(error, "export snippets");
  }
}

export async function importSnippets(
  data: SnippetExportData,
  overwrite: boolean,
): Promise<{
  success: boolean;
  snippetsImported: number;
  snippetsSkipped: number;
  snippetsUpdated: number;
  foldersImported: number;
  foldersSkipped: number;
  failed: number;
  errors: string[];
}> {
  try {
    const response = await authApi.post("/snippets/bulk-import", {
      ...data,
      overwrite,
    });
    return response.data;
  } catch (error) {
    throw handleApiError(error, "import snippets");
  }
}
