import { NONE_SELECT_VALUE, type SampleRecord, type SelectOption } from "./types";
import {
  normalizePlateRow,
  validatePlateCoreContext,
  validatePlateWell,
  type StudyContextOption,
  type TrialContextOption,
} from "./plateUtils";

export const TISSUE_TYPE_OPTIONS: SelectOption[] = [
  { value: "Leaf", label: "Leaf 叶" },
  { value: "Root", label: "Root 根" },
  { value: "Stem", label: "Stem 茎" },
  { value: "Seed", label: "Seed 种子" },
  { value: "Flower", label: "Flower 花" },
  { value: "Fruit", label: "Fruit 果" },
  { value: "Meristem", label: "Meristem 分生组织" },
];

export interface ObservationUnitContextOption extends SelectOption {
  studyDbId: string | null;
}

export function buildWellFromRowColumn(
  row: string | null | undefined,
  column: number | string | null | undefined,
) {
  const normalizedRow = normalizePlateRow(row);
  const col = column === null || column === undefined || column === "" ? null : Number(column);
  if (!normalizedRow || col === null || Number.isNaN(col)) return null;
  return `${normalizedRow}${String(col).padStart(2, "0")}`;
}

export function resolveSampleWell(
  row: string | null | undefined,
  column: number | string | null | undefined,
  well: string | null | undefined,
) {
  const explicitWell = String(well ?? "").trim();
  if (explicitWell) return explicitWell;
  return buildWellFromRowColumn(row, column);
}

export function validateSampleObservationUnitStudy(
  payload: { study_id?: unknown; observation_unit_id?: unknown },
  observationUnits: ObservationUnitContextOption[],
) {
  const studyId = optionalId(payload.study_id);
  const observationUnitId = optionalId(payload.observation_unit_id);
  if (!observationUnitId || !studyId) return;

  const unit = observationUnits.find((item) => item.value === observationUnitId);
  if (!unit) throw new Error("所选观测单元不存在");
  if (unit.studyDbId && studyId !== unit.studyDbId) {
    throw new Error("观测单元所属 Study 与样本所选 Study 不一致");
  }
}

export function validateSampleWellUniqueness(
  plateId: string,
  well: string,
  existingSamples: SampleRecord[],
  excludeSampleId?: string | null,
) {
  const normalizedWell = well.trim().toUpperCase();
  const duplicate = existingSamples.find((sample) => {
    if (excludeSampleId && sample.id === excludeSampleId) return false;
    if (sample.plate_id !== plateId) return false;
    const sampleWell = resolveSampleWell(sample.row, sample.column, sample.well);
    return sampleWell?.trim().toUpperCase() === normalizedWell;
  });
  if (duplicate) {
    throw new Error(`孔位 ${well} 在该样本板内已被样本「${duplicate.sample_name || duplicate.id}」占用`);
  }
}

export function validateSamplePayload(
  payload: {
    program_id?: unknown;
    trial_id?: unknown;
    study_id?: unknown;
    observation_unit_id?: unknown;
    plate_id?: unknown;
    row?: unknown;
    column?: unknown;
    well?: unknown;
  },
  context: {
    plateFormat?: string | null;
    trials: TrialContextOption[];
    studies: StudyContextOption[];
    observationUnits: ObservationUnitContextOption[];
    existingSamples: SampleRecord[];
    sampleDbId?: string | null;
  },
) {
  validatePlateCoreContext(payload, context.trials, context.studies);
  validateSampleObservationUnitStudy(payload, context.observationUnits);

  const plateId = optionalId(payload.plate_id);
  const row = optionalText(payload.row);
  const column = optionalNumber(payload.column);
  const well = resolveSampleWell(row, column, optionalText(payload.well));

  validatePlateWell(context.plateFormat ?? null, row, column, well);

  if (plateId && well) {
    validateSampleWellUniqueness(plateId, well, context.existingSamples, context.sampleDbId);
  }
}

export function resolveContextFromPlate(
  plateId: string | null,
  plates: Array<{ id: string; program_id?: string | null; trial_id?: string | null; study_id?: string | null }>,
) {
  if (!plateId) {
    return {
      program_id: NONE_SELECT_VALUE,
      trial_id: NONE_SELECT_VALUE,
      study_id: NONE_SELECT_VALUE,
    };
  }
  const plate = plates.find((item) => item.id === plateId);
  return {
    program_id: plate?.program_id || NONE_SELECT_VALUE,
    trial_id: plate?.trial_id || NONE_SELECT_VALUE,
    study_id: plate?.study_id || NONE_SELECT_VALUE,
  };
}

export function resolveContextFromObservationUnit(
  observationUnitId: string | null,
  observationUnits: ObservationUnitContextOption[],
) {
  if (!observationUnitId) return { study_id: NONE_SELECT_VALUE };
  const unit = observationUnits.find((item) => item.value === observationUnitId);
  return { study_id: unit?.studyDbId || NONE_SELECT_VALUE };
}

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

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

function optionalNumber(value: unknown) {
  const normalized = optionalText(value);
  if (normalized === null) return null;
  const parsed = Number(normalized);
  return Number.isNaN(parsed) ? null : parsed;
}
