export type FormulaDataType = 'BOOLEAN' | 'DECIMAL' | 'DECIMAL_LIST' | 'TEXT';
export type FormulaVersionStatus = 'PRE_RELEASE' | 'PUBLISHED';

export interface FormulaVersionCandidate {
  formulaEnabled: boolean;
  id: string;
  isCurrent: boolean;
  status: FormulaVersionStatus;
}

export interface FormulaBindingCandidate {
  batchMode: string;
  controlRole: string;
  fieldDataType: FormulaDataType;
  id: string;
  readSource: string;
  status: string;
  writeTarget: string;
}

export interface FormulaBindingRequest {
  formulaVersionId: string;
  operationCode: string;
  parameterBindings: Record<string, string>;
  resultBindingId: string;
}

export interface FormulaParameterSlot {
  code: string;
  name: string;
  required: boolean;
  type: FormulaDataType;
}

export interface TemplateFormulaVersion extends FormulaVersionCandidate {
  formulaCode: string;
  formulaName: string;
  resultType: FormulaDataType;
  slots: FormulaParameterSlot[];
}

export interface FormulaResultLockSnapshot {
  locks: Array<{ lock: string; tag: string }>;
  primaryTag: string;
}

export interface FormulaBindingLockSnapshot {
  bindingId: string;
  controlRole: string;
  controlTag: string;
  lock: string;
}

export interface TemplateFormulaBinding {
  formulaVersionId: string;
  id: string;
  jieguoSuoKuaizhao?: FormulaBindingLockSnapshot[];
  operationCode: string;
  parameterBindings: Record<string, string>;
  resultBindingId: string;
  status: 'ACTIVE' | 'CANCELLED' | 'PENDING' | 'REMOVED';
  version: number;
}

export interface FormulaMappingCheck {
  downstreamFormulaBindingIds: string[];
  expectedVersions: Record<string, number>;
  operationCode: string;
}

export interface FormulaMappingContext {
  bindings: TemplateFormulaBinding[];
  copiedPendingBindingIds?: string[];
  inheritedFormulaLockBindingIds?: string[];
  upgradeOperationCode?: string;
  versions: TemplateFormulaVersion[];
}

function compatible(formulaType: FormulaDataType, fieldType: FormulaDataType): boolean {
  if (formulaType === 'DECIMAL_LIST') return false;
  if (formulaType === 'DECIMAL') return fieldType === 'DECIMAL';
  if (formulaType === 'TEXT') return fieldType === 'TEXT';
  return fieldType === 'BOOLEAN';
}

function activePrimary(binding: FormulaBindingCandidate): boolean {
  return binding.status === 'ACTIVE' && binding.controlRole === 'PRIMARY';
}

export function formulaVersionOptions(versions: FormulaVersionCandidate[]): Array<{ id: string; risk: boolean; selectable: boolean }> {
  return versions
    .filter((version) => version.formulaEnabled && (version.status === 'PRE_RELEASE' || version.status === 'PUBLISHED'))
    .map((version) => ({
      id: version.id,
      risk: version.status === 'PRE_RELEASE',
      selectable: version.status === 'PRE_RELEASE' || version.isCurrent,
    }));
}

export function parameterBindingCandidates(type: FormulaDataType, bindings: FormulaBindingCandidate[]): string[] {
  return bindings.filter((binding) => activePrimary(binding) && compatible(type, binding.fieldDataType)).map((binding) => binding.id);
}

export function resultBindingCandidates(type: FormulaDataType, bindings: FormulaBindingCandidate[]): string[] {
  return bindings.filter((binding) => activePrimary(binding)
    && binding.readSource === 'NONE'
    && binding.writeTarget === 'ELN_RECORD'
    && binding.batchMode === 'RECORD_PRIVATE'
    && compatible(type, binding.fieldDataType)).map((binding) => binding.id);
}

export function buildFormulaBindingRequest(request: FormulaBindingRequest): FormulaBindingRequest {
  return {
    formulaVersionId: request.formulaVersionId,
    parameterBindings: { ...request.parameterBindings },
    resultBindingId: request.resultBindingId,
    operationCode: request.operationCode,
  };
}
