import { authenticatedFetch, getApiUrl } from "@/lib/auth";
import type {
  CloneProjectPayload,
  CreateProjectPayload,
  ProjectParticipant,
  ProjectSummary,
} from "@/types/projects";

function getErrorMessage(payload: unknown, fallback: string) {
  if (payload && typeof payload === "object" && "message" in payload) {
    const { message } = payload as { message?: unknown };
    if (typeof message === "string" && message.trim().length > 0) {
      return message;
    }
  }
  return fallback;
}

async function parseJsonSafe(response: Response) {
  try {
    return await response.json();
  } catch {
    return null;
  }
}

async function apiCall<T>(path: string, init?: RequestInit, fallbackError = "Erreur API") {
  const response = await authenticatedFetch(getApiUrl(), path, init);
  const payload = await parseJsonSafe(response);

  if (!response.ok) {
    throw new Error(getErrorMessage(payload, fallbackError));
  }

  return payload as T;
}

function dedupeProjects(projects: ProjectSummary[]) {
  const byId = new Map<string, ProjectSummary>();

  for (const project of projects) {
    byId.set(project.id, project);
  }

  return Array.from(byId.values()).sort((a, b) => {
    return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
  });
}

export function getMyProjects() {
  return apiCall<ProjectSummary[]>("/projects", undefined, "Impossible de charger les projets")
    .then((projects) => dedupeProjects(projects));
}

export function getProjectById(projectId: string) {
  return apiCall<ProjectSummary>(`/projects/${projectId}`, undefined, "Impossible de charger ce projet");
}

export function createProject(payload: CreateProjectPayload) {
  return apiCall<ProjectSummary>(
    "/projects",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    },
    "Impossible de creer le projet",
  );
}

export function updateProject(projectId: string, payload: Partial<CreateProjectPayload>) {
  return apiCall<ProjectSummary>(
    `/projects/${projectId}`,
    {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    },
    "Impossible de mettre a jour le projet",
  );
}

export function cloneProject(projectId: string, payload: CloneProjectPayload) {
  return apiCall<ProjectSummary>(
    `/projects/${projectId}/clone`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    },
    "Impossible de cloner ce projet",
  );
}

export function getProjectParticipants(projectId: string) {
  return apiCall<ProjectParticipant[]>(
    `/projects/${projectId}/participants`,
    undefined,
    "Impossible de charger les participants",
  );
}

export function addProjectParticipant(projectId: string, userId: string) {
  return apiCall<ProjectParticipant>(
    `/projects/${projectId}/participants`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ userId }),
    },
    "Impossible d'ajouter ce participant",
  );
}

export function removeProjectParticipant(projectId: string, participantUserId: string) {
  return apiCall<{ removed: boolean }>(
    `/projects/${projectId}/participants/${participantUserId}`,
    {
      method: "DELETE",
    },
    "Impossible de retirer ce participant",
  );
}

export function getProjectDefaultAvatars(projectId: string) {
  return apiCall<string[]>(
    `/projects/${projectId}/default-project-avatars`,
    undefined,
    "Impossible de charger les avatars",
  );
}

export function uploadProjectPhoto(projectId: string, blob: Blob, bgColor: string) {
  const formData = new FormData();
  formData.append("file", blob, "project-photo.png");
  formData.append("bgColor", bgColor);
  return apiCall<ProjectSummary>(
    `/projects/${projectId}/photo`,
    { method: "POST", body: formData },
    "Impossible d'uploader la photo",
  );
}

export function deleteProjectPhoto(projectId: string) {
  return apiCall<ProjectSummary>(
    `/projects/${projectId}/photo`,
    { method: "DELETE" },
    "Impossible de supprimer la photo",
  );
}

export function setProjectDefaultAvatar(projectId: string, avatarUrl: string, bgColor?: string) {
  return apiCall<ProjectSummary>(
    `/projects/${projectId}/avatar`,
    {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ avatarUrl, bgColor }),
    },
    "Impossible de definir l'avatar",
  );
}
