import type { BreedingMethod } from "@/lib/api/types.gen";
import { loadBreedingMethodOptions, invalidateBreedingMethodOptions } from "@/services/dropdownCache";
import { getAuthToken } from "@/utils/token";
import type { BreedingMethodRecord } from "./types";

interface BrapiPagination {
  currentPage: number;
  pageSize: number;
  totalCount: number;
  totalPages: number;
}

interface BrapiListResponse<T> {
  metadata: {
    pagination: BrapiPagination;
    status: Array<Record<string, unknown>>;
    datafiles: Array<Record<string, unknown>>;
  };
  result: {
    data: T[];
  };
}

interface BrapiSingleResponse<T> {
  metadata: {
    pagination: BrapiPagination;
    status: Array<Record<string, unknown>>;
    datafiles: Array<Record<string, unknown>>;
  };
  result: T;
}

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

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 mapBreedingMethod = (method: BreedingMethod): BreedingMethodRecord => {
  const name = method.breedingMethodName ?? null;
  return {
    id: method.breedingMethodDbId || "",
    breedingMethodDbId: method.breedingMethodDbId || "",
    breedingMethodName: name,
    name,
    abbreviation: method.abbreviation ?? null,
    description: method.description ?? null,
  };
};

async function fetchBreedingMethodList(): Promise<BreedingMethod[]> {
  const response = await request<BrapiListResponse<BreedingMethod>>("/brapi/v2/breedingmethods?page=0&pageSize=10");
  return response.result?.data ?? [];
}

const toRequestBody = (payload: Record<string, unknown>) => {
  const breedingMethodName = emptyToNull(payload.breedingMethodName ?? payload.name);
  if (!breedingMethodName) {
    throw new Error("???????");
  }
  return {
    breedingMethodName,
    abbreviation: emptyToNull(payload.abbreviation),
    description: emptyToNull(payload.description),
  };
};

export async function fetchBreedingMethodRows(): Promise<BreedingMethodRecord[]> {
  const methods = await fetchBreedingMethodList();
  return methods.map((method) => mapBreedingMethod(method));
}

export async function createBreedingMethodRow(payload: Record<string, unknown>): Promise<BreedingMethodRecord> {
  const response = await request<BrapiListResponse<BreedingMethod>>("/brapi/v2/breedingmethods", {
    method: "POST",
    body: JSON.stringify([toRequestBody(payload)]),
  });
  const created = response.result.data[0];
  invalidateBreedingMethodOptions();
  return mapBreedingMethod(created);
}

export async function updateBreedingMethodRow(id: string, payload: Record<string, unknown>): Promise<BreedingMethodRecord> {
  const response = await request<BrapiSingleResponse<BreedingMethod>>(
    `/brapi/v2/breedingmethods/${encodeURIComponent(id)}`,
    {
      method: "PUT",
      body: JSON.stringify(toRequestBody(payload)),
    },
  );
  invalidateBreedingMethodOptions();
  return mapBreedingMethod(response.result);
}

export async function deleteBreedingMethodRow(id: string): Promise<void> {
  await request<BrapiSingleResponse<BreedingMethod>>(
    `/brapi/v2/breedingmethods/${encodeURIComponent(id)}`,
    { method: "DELETE" },
  );
  invalidateBreedingMethodOptions();
}

export async function fetchBreedingMethodOptions(force = false): Promise<Array<{ value: string; label: string }>> {
  return loadBreedingMethodOptions(force);
}
