import type { GermplasmAttributeValue } from "@/lib/api/types.gen";
import { toBrapiIsoDateTime } from "@/lib/brapiIso";
import { getAuthToken } from "@/utils/token";
import { type AttributeValueRecord, NONE_SELECT_VALUE } from "./attributeTypes";

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;
}

type AttributeValuePayload = Partial<Record<
  | "attribute_id"
  | "germplasm_id"
  | "value"
  | "determined_date",
  unknown
>>;

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 optionalText = (value: unknown) => {
  const normalized = String(value ?? "").trim();
  if (!normalized || normalized === NONE_SELECT_VALUE) return null;
  return normalized;
};

const formatDeterminedDate = (value: unknown) => {
  if (value === null || value === undefined || value === "") return null;
  const text = String(value);
  return text.length >= 10 ? text.slice(0, 10) : text;
};

export const mapAttributeValue = (row: GermplasmAttributeValue): AttributeValueRecord => {
  const determinedDate = formatDeterminedDate(row.determinedDate);
  return {
    id: row.attributeValueDbId || "",
    attributeValueDbId: row.attributeValueDbId || "",
    attributeDbId: row.attributeDbId ?? null,
    attribute_id: row.attributeDbId ?? null,
    attributeName: row.attributeName ?? null,
    germplasmDbId: row.germplasmDbId ?? null,
    germplasm_id: row.germplasmDbId ?? null,
    germplasmName: row.germplasmName ?? null,
    value: row.value ?? null,
    determinedDate,
    determined_date: determinedDate,
  };
};

export function normalizeAttributeValueFormData(record: AttributeValueRecord): Record<string, unknown> {
  return {
    ...record,
    attribute_id: record.attribute_id && record.attribute_id !== NONE_SELECT_VALUE ? record.attribute_id : NONE_SELECT_VALUE,
    germplasm_id: record.germplasm_id && record.germplasm_id !== NONE_SELECT_VALUE ? record.germplasm_id : NONE_SELECT_VALUE,
  };
}

const toRequestBody = (payload: AttributeValuePayload) => {
  const attributeDbId = optionalText(payload.attribute_id);
  const germplasmDbId = optionalText(payload.germplasm_id);
  const value = optionalText(payload.value);

  if (!attributeDbId) throw new Error("请选择属性定");
  if (!germplasmDbId) throw new Error("请选择种质材料");
  if (!value) throw new Error("请填写属性");

  return {
    attributeDbId,
    germplasmDbId,
    value,
    ...(toBrapiIsoDateTime(payload.determined_date)
      ? { determinedDate: toBrapiIsoDateTime(payload.determined_date) }
      : {}),
  };
};

export async function fetchAttributeValueRows(germplasmDbId?: string): Promise<AttributeValueRecord[]> {
  const query = germplasmDbId
    ? `?page=0&pageSize=10&germplasmDbId=${encodeURIComponent(germplasmDbId)}`
    : "?page=0&pageSize=10";
  const response = await request<BrapiListResponse<GermplasmAttributeValue>>(`/brapi/v2/attributevalues${query}`);
  return (response.result?.data ?? []).map(mapAttributeValue);
}

export async function fetchAttributeValueDetail(id: string): Promise<AttributeValueRecord> {
  const response = await request<BrapiSingleResponse<GermplasmAttributeValue>>(
    `/brapi/v2/attributevalues/${encodeURIComponent(id)}`,
  );
  return mapAttributeValue(response.result);
}

export async function createAttributeValueRow(payload: AttributeValuePayload): Promise<AttributeValueRecord> {
  const response = await request<BrapiListResponse<GermplasmAttributeValue>>("/brapi/v2/attributevalues", {
    method: "POST",
    body: JSON.stringify([toRequestBody(payload)]),
  });
  return mapAttributeValue(response.result.data[0]);
}

export async function updateAttributeValueRow(id: string, payload: AttributeValuePayload): Promise<AttributeValueRecord> {
  const response = await request<BrapiSingleResponse<GermplasmAttributeValue>>(
    `/brapi/v2/attributevalues/${encodeURIComponent(id)}`,
    {
      method: "PUT",
      body: JSON.stringify(toRequestBody(payload)),
    },
  );
  return mapAttributeValue(response.result);
}
