import { NONE_SELECT_VALUE, type SelectOption } from "./types";

export const PLATE_FORMAT_OPTIONS: SelectOption[] = [
  { value: "PLATE_96", label: "96 孔板 (PLATE_96)" },
  { value: "TUBES", label: "试管/无板 (TUBES)" },
];

export const SAMPLE_TYPE_OPTIONS: SelectOption[] = [
  { value: "DNA", label: "DNA" },
  { value: "RNA", label: "RNA" },
  { value: "TISSUE", label: "TISSUE 组织" },
  { value: "MIXED", label: "MIXED 混合" },
];

export const PLATE_96_ROWS = ["A", "B", "C", "D", "E", "F", "G", "H"] as const;
export const PLATE_96_MAX_COLUMN = 12;

export interface TrialContextOption extends SelectOption {
  programDbId: string | null;
}

export interface StudyContextOption extends SelectOption {
  trialDbId: string | null;
  programDbId: string | null;
}

export function optionOrNone(label: string, options: SelectOption[]) {
  return [{ value: NONE_SELECT_VALUE, label }, ...options];
}

export function optionLabel(options: SelectOption[], value: unknown) {
  const text = String(value ?? "").trim();
  if (!text || text === NONE_SELECT_VALUE) return "—";
  return options.find((option) => option.value === text)?.label || text;
}

export function normalizePlateRow(row: string | null | undefined) {
  return String(row ?? "").trim().toUpperCase();
}

export function validatePlateWell(
  plateFormat: string | null | undefined,
  row: string | null | undefined,
  column: number | string | null | undefined,
  well: string | null | undefined,
) {
  if (!plateFormat || plateFormat === "TUBES" || plateFormat === NONE_SELECT_VALUE) return;

  if (plateFormat !== "PLATE_96") return;

  const normalizedRow = normalizePlateRow(row);
  const col = column === null || column === undefined || column === "" ? null : Number(column);

  if (normalizedRow && !PLATE_96_ROWS.includes(normalizedRow as typeof PLATE_96_ROWS[number])) {
    throw new Error(`96 孔板行号需在 A–H，当前为 ${normalizedRow}`);
  }
  if (col !== null && !Number.isNaN(col) && (col < 1 || col > PLATE_96_MAX_COLUMN)) {
    throw new Error(`96 孔板列号需在 1–${PLATE_96_MAX_COLUMN}，当前为 ${col}`);
  }
  if (well) {
    const match = /^([A-H])(\d{1,2})$/i.exec(well.trim());
    if (match) {
      const wellRow = match[1].toUpperCase();
      const wellCol = Number(match[2]);
      if (!PLATE_96_ROWS.includes(wellRow as typeof PLATE_96_ROWS[number]) || wellCol < 1 || wellCol > PLATE_96_MAX_COLUMN) {
        throw new Error(`孔位 ${well} 超出 96 孔板规格 (A01–H12)`);
      }
    }
  }
}

export function validatePlateCoreContext(
  payload: {
    program_id?: unknown;
    trial_id?: unknown;
    study_id?: unknown;
  },
  trials: TrialContextOption[],
  studies: StudyContextOption[],
) {
  const programId = optionalId(payload.program_id);
  const trialId = optionalId(payload.trial_id);
  const studyId = optionalId(payload.study_id);

  if (studyId) {
    const study = studies.find((item) => item.value === studyId);
    if (!study) throw new Error("所选 Study 不存在");
    if (trialId && study.trialDbId && trialId !== study.trialDbId) {
      throw new Error("Study 所属 Trial 与所选 Trial 不一致");
    }
    if (programId && study.programDbId && programId !== study.programDbId) {
      throw new Error("Study 所属 Program 与所选 Program 不一致");
    }
  }

  if (trialId) {
    const trial = trials.find((item) => item.value === trialId);
    if (!trial) throw new Error("所选 Trial 不存在");
    if (programId && trial.programDbId && programId !== trial.programDbId) {
      throw new Error("Trial 所属 Program 与所选 Program 不一致");
    }
  }
}

export function resolveContextFromStudy(
  studyId: string | null,
  studies: StudyContextOption[],
): { trial_id: string; program_id: string } {
  if (!studyId) return { trial_id: NONE_SELECT_VALUE, program_id: NONE_SELECT_VALUE };
  const study = studies.find((item) => item.value === studyId);
  return {
    trial_id: study?.trialDbId || NONE_SELECT_VALUE,
    program_id: study?.programDbId || NONE_SELECT_VALUE,
  };
}

export function resolveContextFromTrial(
  trialId: string | null,
  trials: TrialContextOption[],
): { program_id: string } {
  if (!trialId) return { program_id: NONE_SELECT_VALUE };
  const trial = trials.find((item) => item.value === trialId);
  return { program_id: trial?.programDbId || NONE_SELECT_VALUE };
}

function optionalId(value: unknown) {
  const normalized = String(value ?? "").trim();
  if (!normalized || normalized === NONE_SELECT_VALUE) return null;
  return normalized;
}
