import { getAuthToken } from "@/utils/token";
import { loadPersonOptions } from "@/services/dropdownCache";
import { NONE_SELECT_VALUE, type ProgramRecord, type SelectOption } 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;
}

interface CropResponse {
  id: string;
  crop_name: string | null;
}

type ProgramPayload = Partial<Record<
  "id" | "name" | "abbreviation" | "objective" | "documentationurl" | "funding_information" | "program_type" | "crop_id" | "lead_person_id",
  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 optionalNumber = (value: unknown) => {
  const normalized = optionalText(value);
  if (normalized === null) return null;
  const parsed = Number(normalized);
  return Number.isNaN(parsed) ? null : parsed;
};

const programName = (payload: ProgramPayload) => {
  const name = optionalText(payload.name);
  if (!name) throw new Error("请填写项目名");
  return name;
};

const mapProgram = (program: ProgramRecord): ProgramRecord => ({
  ...program,
  id: program.programDbId,
  name: program.name || program.programName,
  crop_id: program.crop_id || program.cropDbId,
  crop_name: program.crop_name || program.cropName,
  lead_person_id: program.lead_person_id || program.leadPersonDbId,
  lead_person_name: program.lead_person_name || program.leadPersonName,
  funding_information: program.funding_information || program.fundingInformation,
  documentationurl: program.documentationurl || program.documentationURL,
  program_type: program.program_type ?? program.programType,
});

const toRequestBody = (payload: ProgramPayload) => ({
  name: programName(payload),
  abbreviation: optionalText(payload.abbreviation),
  objective: optionalText(payload.objective),
  documentationurl: optionalText(payload.documentationurl),
  funding_information: optionalText(payload.funding_information),
  program_type: optionalNumber(payload.program_type),
  crop_id: optionalText(payload.crop_id),
  lead_person_id: optionalText(payload.lead_person_id),
});

export async function fetchProgramRows(): Promise<ProgramRecord[]> {
  const response = await request<BrapiListResponse<ProgramRecord>>("/brapi/v2/programs?page=0&pageSize=10");
  return response.result.data.map(mapProgram);
}

export async function fetchProgramOptions(force = false): Promise<{ crops: SelectOption[]; people: SelectOption[] }> {
  const [crops, people] = await Promise.all([
    request<CropResponse[]>("/api/dictionaries/crops"),
    loadPersonOptions(force),
  ]);

  return {
    crops: crops.map((crop) => ({
      value: crop.id,
      label: crop.crop_name || crop.id,
    })),
    people,
  };
}

export async function createProgramRow(payload: ProgramPayload): Promise<ProgramRecord> {
  const response = await request<BrapiListResponse<ProgramRecord>>("/brapi/v2/programs", {
    method: "POST",
    body: JSON.stringify([toRequestBody(payload)]),
  });
  return mapProgram(response.result.data[0]);
}

export async function updateProgramRow(id: string, payload: ProgramPayload): Promise<ProgramRecord> {
  const response = await request<BrapiSingleResponse<ProgramRecord>>(`/brapi/v2/programs/${encodeURIComponent(id)}`, {
    method: "PUT",
    body: JSON.stringify(toRequestBody(payload)),
  });
  return mapProgram(response.result);
}

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