import type {
  EvaluationFormApiResponse,
  EvaluationFormData,
  EvaluationItemEvaluation,
  UpdateEvaluationFormPayload,
} from "../types/evaluation-form.types";

const API_BASE_URL =
  process.env.NEXT_PUBLIC_API_URL?.replace(
    /\/$/,
    "",
  ) ||
  "http://localhost:3001/api/v1";

function getAccessToken():
  | string
  | null {
  if (
    typeof window ===
    "undefined"
  ) {
    return null;
  }

  return (
    window.localStorage.getItem(
      "accessToken",
    ) ||
    window.localStorage.getItem(
      "access_token",
    ) ||
    window.localStorage.getItem(
      "token",
    )
  );
}

function buildHeaders(
  json = false,
): Record<string, string> {
  const token =
    getAccessToken();

  const headers:
    Record<string, string> = {
      Accept:
        "application/json",
    };

  if (json) {
    headers[
      "Content-Type"
    ] =
      "application/json";
  }

  if (token) {
    headers.Authorization =
      `Bearer ${token}`;
  }

  return headers;
}

async function getErrorMessage(
  response: Response,
): Promise<string> {
  try {
    const body =
      await response.json();

    if (
      typeof body?.message ===
      "string"
    ) {
      return body.message;
    }

    if (
      Array.isArray(
        body?.message,
      )
    ) {
      return body.message.join(
        ", ",
      );
    }
  } catch {
    // fallback
  }

  return `Request failed with status ${response.status}`;
}

function normalizeEvaluation(
  value:
    | EvaluationItemEvaluation
    | EvaluationItemEvaluation[]
    | null
    | undefined,
): EvaluationItemEvaluation | null {
  if (
    Array.isArray(value)
  ) {
    return value[0] ?? null;
  }

  return value ?? null;
}

function normalizeData(
  data: EvaluationFormData,
): EvaluationFormData {
  return {
    ...data,

    items:
      data.items.map(
        (item) => ({
          ...item,

          evaluation:
            normalizeEvaluation(
              item.evaluation,
            ),
        }),
      ),
  };
}

export async function getEvaluationForm(
  assignmentId: number,
): Promise<EvaluationFormData> {
  const response =
    await fetch(
      `${API_BASE_URL}/progress-reports/assignments/${assignmentId}/evaluations/submitted`,
      {
        method: "GET",

        headers:
          buildHeaders(),

        credentials:
          "include",

        cache:
          "no-store",
      },
    );

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

  const result =
    (await response.json()) as EvaluationFormApiResponse;

  if (
    !result.success ||
    !result.data
  ) {
    throw new Error(
      result.message ||
        "Unable to load evaluation form.",
    );
  }

  return normalizeData(
    result.data,
  );
}

export async function updateEvaluationForm(
  assignmentId: number,
  payload:
    UpdateEvaluationFormPayload,
): Promise<EvaluationFormData> {
  const response =
    await fetch(
      `${API_BASE_URL}/progress-reports/assignments/${assignmentId}/evaluations/submitted`,
      {
        method:
          "PATCH",

        headers:
          buildHeaders(
            true,
          ),

        credentials:
          "include",

        cache:
          "no-store",

        body:
          JSON.stringify(
            payload,
          ),
      },
    );

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

  const result =
    (await response.json()) as EvaluationFormApiResponse;

  if (
    !result.success ||
    !result.data
  ) {
    throw new Error(
      result.message ||
        "Unable to update evaluation form.",
    );
  }

  return normalizeData(
    result.data,
  );
}