import { authenticatedFetch, getApiUrl, getCurrentProjectId } from "@/lib/auth";
import type {
  PredictionActivity,
  PredictionBoardResponse,
  PredictionCard,
  PredictionEntry,
  PredictionFinalizeResponse,
  PredictionScoringEntry,
  PredictionScoreboardItem,
  PredictionSetOutcomesPayload,
  UpsertPredictionPayload,
  PredictionValidateScoresPayload,
} from "@/types/predictions";

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 buildPredictionsPath(pathSuffix: string, projectId?: string | null) {
  const scopedProjectId = projectId ?? getCurrentProjectId();

  if (!scopedProjectId) {
    throw new Error("Aucun projet actif. Cree ou selectionne un projet.");
  }

  const basePath = `/projects/${scopedProjectId}/predictions`;

  return `${basePath}${pathSuffix}`;
}

export function getPredictionCards(projectId?: string | null) {
  return apiCall<PredictionCard[]>(
    buildPredictionsPath("/cards", projectId),
    undefined,
    "Impossible de charger les cartes",
  );
}

export function getMyPredictionEntries(projectId?: string | null) {
  return apiCall<PredictionEntry[]>(
    buildPredictionsPath("/my-entries", projectId),
    undefined,
    "Impossible de charger tes pronostics",
  );
}

export function upsertPredictionEntry(
  cardId: string,
  body: UpsertPredictionPayload,
  projectId?: string | null,
) {
  return apiCall<PredictionEntry>(
    buildPredictionsPath(`/cards/${cardId}/my-entry`, projectId),
    {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(body),
    },
    "Impossible de sauvegarder le pronostic",
  );
}

export function getPredictionActivity(projectId?: string | null) {
  return apiCall<PredictionActivity[]>(
    buildPredictionsPath("/activity", projectId),
    undefined,
    "Impossible de charger l'historique",
  );
}

export function getPredictionBoard(projectId?: string | null, selectedBabyIndex?: number) {
  const query = selectedBabyIndex ? `?selectedBabyIndex=${selectedBabyIndex}` : "";
  return apiCall<PredictionBoardResponse>(
    buildPredictionsPath(`/board${query}`, projectId),
    undefined,
    "Impossible de charger le recap des pronostics",
  );
}

export function getPredictionScoreboard(projectId?: string | null) {
  return apiCall<PredictionScoreboardItem[]>(
    buildPredictionsPath("/scoreboard", projectId),
    undefined,
    "Impossible de charger le classement",
  );
}

export function closePredictionGame(projectId?: string | null) {
  return apiCall<{ status: "CLOSED" }>(
    buildPredictionsPath("/game/close", projectId),
    { method: "POST" },
    "Impossible de cloturer le concours",
  );
}

export function openPredictionGame(projectId?: string | null) {
  return apiCall<{ status: "OPEN" }>(
    buildPredictionsPath("/game/open", projectId),
    { method: "POST" },
    "Impossible de reouvrir le concours",
  );
}

export function finalizePredictionGame(projectId?: string | null) {
  return apiCall<PredictionFinalizeResponse>(
    buildPredictionsPath("/game/finalize", projectId),
    { method: "POST" },
    "Impossible de valider la fin du concours",
  );
}

export function setPredictionOutcomes(
  cardId: string,
  payload: PredictionSetOutcomesPayload,
  projectId?: string | null,
) {
  return apiCall(
    buildPredictionsPath(`/cards/${cardId}/outcomes`, projectId),
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    },
    "Impossible d'enregistrer les valeurs reelles",
  );
}

export function suggestPredictionScores(
  cardId: string,
  projectId?: string | null,
  selectedBabyIndex?: number,
) {
  const query = selectedBabyIndex ? `?selectedBabyIndex=${selectedBabyIndex}` : "";
  return apiCall<PredictionScoringEntry[]>(
    buildPredictionsPath(`/cards/${cardId}/suggest-scores${query}`, projectId),
    {
      method: "POST",
    },
    "Impossible de lancer le calcul automatique",
  );
}

export function validatePredictionScores(
  entryId: string,
  payload: PredictionValidateScoresPayload,
  projectId?: string | null,
) {
  return apiCall<PredictionEntry>(
    buildPredictionsPath(`/entries/${entryId}/scores`, projectId),
    {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    },
    "Impossible de valider les points",
  );
}
