import { DEFAULT_LIST_PAGE, DEFAULT_LIST_PAGE_SIZE } from "@/constants/api";
import { getAuthToken } from "@/utils/token";
import type { OntologyRecord } from "@/services/dictionaryService";

interface BrapiListResponse<T> {
  result: { data: T[] };
}

interface BrapiSingleResponse<T> {
  result: T;
}

type OntologyApiRecord = Omit<OntologyRecord, "id">;

type OntologyPayload = Partial<
  Pick<OntologyRecord, "ontologyName" | "version" | "documentationURL" | "authors" | "copyright" | "licence" | "description">
>;

const apiBase = () => {
  if (typeof window !== "undefined") return "";
  return process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8081";
};

async function request<T>(path: string, init?: RequestInit): Promise<T> {
  const token = getAuthToken();
  const response = await fetch(`${apiBase()}${path}`, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(init?.headers || {}),
    },
  });

  if (!response.ok) {
    const detail = await response.text();
    throw new Error(detail || `?????${response.status}`);
  }
  return response.json() as Promise<T>;
}

const emptyToNull = (value: unknown) => {
  const normalized = String(value ?? "").trim();
  return normalized ? normalized : null;
};

export const mapOntology = (ontology: OntologyApiRecord): OntologyRecord => ({
  ...ontology,
  id: ontology.ontologyDbId,
  ontologyName: ontology.ontologyName ?? ontology.ontology_name ?? null,
  ontology_name: ontology.ontologyName ?? ontology.ontology_name ?? null,
  documentationURL: ontology.documentationURL ?? ontology.documentationurl ?? null,
  documentationurl: ontology.documentationURL ?? ontology.documentationurl ?? null,
});

const toRequestBody = (payload: Record<string, unknown>): OntologyPayload => ({
  ontologyName: emptyToNull(payload.ontologyName ?? payload.ontology_name),
  version: emptyToNull(payload.version),
  documentationURL: emptyToNull(payload.documentationURL ?? payload.documentationurl),
  authors: emptyToNull(payload.authors),
  copyright: emptyToNull(payload.copyright),
  licence: emptyToNull(payload.licence),
  description: emptyToNull(payload.description),
});

export async function fetchOntologyRows(page = DEFAULT_LIST_PAGE, pageSize = DEFAULT_LIST_PAGE_SIZE): Promise<OntologyRecord[]> {
  const response = await request<BrapiListResponse<OntologyApiRecord>>(
    `/brapi/v2/ontologies?page=${encodeURIComponent(String(page))}&pageSize=${encodeURIComponent(String(pageSize))}`,
  );
  return response.result.data.map(mapOntology);
}

export async function fetchOntologyDetail(ontologyDbId: string): Promise<OntologyRecord> {
  const response = await request<BrapiSingleResponse<OntologyApiRecord>>(
    `/brapi/v2/ontologies/${encodeURIComponent(ontologyDbId)}`,
  );
  return mapOntology(response.result);
}

export async function createOntologyRow(payload: Record<string, unknown>): Promise<OntologyRecord> {
  const body = toRequestBody(payload);
  if (!body.ontologyName) {
    throw new Error("???????");
  }
  const response = await request<BrapiListResponse<OntologyApiRecord>>("/brapi/v2/ontologies", {
    method: "POST",
    body: JSON.stringify([body]),
  });
  const ontology = response.result.data[0];
  if (!ontology) {
    throw new Error("??????????????");
  }
  return mapOntology(ontology);
}

export async function updateOntologyRow(ontologyDbId: string, payload: Record<string, unknown>): Promise<OntologyRecord> {
  const response = await request<BrapiSingleResponse<OntologyApiRecord>>(
    `/brapi/v2/ontologies/${encodeURIComponent(ontologyDbId)}`,
    {
      method: "PUT",
      body: JSON.stringify(toRequestBody(payload)),
    },
  );
  return mapOntology(response.result);
}

export async function deleteOntologyRow(ontologyDbId: string): Promise<void> {
  await request<BrapiSingleResponse<OntologyApiRecord>>(
    `/brapi/v2/ontologies/${encodeURIComponent(ontologyDbId)}`,
    { method: "DELETE" },
  );
}
