import type { GermplasmAttribute } from "@/lib/api/types.gen";
import { getAuthToken } from "@/utils/token";
import {
  readAttributeDataType,
  type AttributeDataType,
  type AttributeRecord,
  type SelectOption,
  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;
}

interface CommonCropNamesResponse {
  result: {
    data: string[];
  };
}

type AttributePayload = Partial<Record<
  | "attributeName"
  | "attributeCategory"
  | "attributeDescription"
  | "attributePUI"
  | "crop_id"
  | "dataType",
  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;
};

export const mapAttribute = (attribute: GermplasmAttribute): AttributeRecord => {
  const cropName = attribute.commonCropName ?? null;
  return {
    id: attribute.attributeDbId || "",
    attributeDbId: attribute.attributeDbId || "",
    attributeName: attribute.attributeName ?? null,
    attributeCategory: attribute.attributeCategory ?? null,
    attributeDescription: attribute.attributeDescription ?? null,
    commonCropName: cropName,
    crop_id: cropName,
    dataType: readAttributeDataType(attribute),
    attributePUI: attribute.attributePUI ?? null,
  };
};

export function normalizeAttributeFormData(record: AttributeRecord): Record<string, unknown> {
  return {
    ...record,
    crop_id: record.crop_id && record.crop_id !== NONE_SELECT_VALUE ? record.crop_id : NONE_SELECT_VALUE,
    dataType: record.dataType && record.dataType !== NONE_SELECT_VALUE ? record.dataType : NONE_SELECT_VALUE,
  };
}

const toRequestBody = (payload: AttributePayload) => {
  const attributeName = optionalText(payload.attributeName);
  if (!attributeName) throw new Error("请填写属性名");

  const dataType = optionalText(payload.dataType) as AttributeDataType | null;
  const scaleName = `${attributeName} scale`;

  return {
    attributeName,
    attributeCategory: optionalText(payload.attributeCategory),
    attributeDescription: optionalText(payload.attributeDescription),
    attributePUI: optionalText(payload.attributePUI),
    ...(optionalText(payload.crop_id) ? { commonCropName: optionalText(payload.crop_id) } : {}),
    ...(dataType
      ? {
        scale: {
          scaleName,
          dataType,
        },
      }
      : {}),
  };
};

export async function fetchAttributeRows(): Promise<AttributeRecord[]> {
  const response = await request<BrapiListResponse<GermplasmAttribute>>("/brapi/v2/attributes?page=0&pageSize=10");
  return (response.result?.data ?? []).map(mapAttribute);
}

export async function fetchAttributeDetail(id: string): Promise<AttributeRecord> {
  const response = await request<BrapiSingleResponse<GermplasmAttribute>>(
    `/brapi/v2/attributes/${encodeURIComponent(id)}`,
  );
  return mapAttribute(response.result);
}

export async function fetchAttributeOptions(): Promise<SelectOption[]> {
  const rows = await fetchAttributeRows();
  return rows.map((row) => ({
    value: row.attributeDbId,
    label: row.attributeCategory
      ? `${row.attributeName || row.attributeDbId} / ${row.attributeCategory}`
      : (row.attributeName || row.attributeDbId),
  })).filter((option) => option.value);
}

export async function fetchAttributeFormOptions(): Promise<{ crops: SelectOption[] }> {
  const cropsResult = await request<CommonCropNamesResponse>("/brapi/v2/commoncropnames?page=0&pageSize=10").catch(() => null);
  return {
    crops: (cropsResult?.result?.data ?? []).map((cropName) => ({
      value: cropName,
      label: cropName,
    })),
  };
}

export async function createAttributeRow(payload: AttributePayload): Promise<AttributeRecord> {
  const response = await request<BrapiListResponse<GermplasmAttribute>>("/brapi/v2/attributes", {
    method: "POST",
    body: JSON.stringify([toRequestBody(payload)]),
  });
  return mapAttribute(response.result.data[0]);
}

export async function updateAttributeRow(id: string, payload: AttributePayload): Promise<AttributeRecord> {
  const response = await request<BrapiSingleResponse<GermplasmAttribute>>(
    `/brapi/v2/attributes/${encodeURIComponent(id)}`,
    {
      method: "PUT",
      body: JSON.stringify(toRequestBody(payload)),
    },
  );
  return mapAttribute(response.result);
}
