/**
 * @typedef {Object} AnalysisModel
 * @property {Object} table
 * @property {string[]} table.columns
 * @property {Array} table.data
 * @property {string} table.data.exception
 * @property {boolean=} table.data.invalid
 * @property {AnalysisException[]} exception
 * @property {Array} exceptionGroup
 * @property {string} exceptionGroup.key
 * @property {AnalysisException[]} exceptionGroup.exception
 * @property {string[]} cover
 * @property {string} result
 */

/**
 * @typedef {Object} AnalysisException
 * @property {string} title
 * @property {string=} cover
 * @property {string=} description
 * @property {Array} descriptions
 * @property {string} descriptions.label
 * @property {string} descriptions.value
 * @property {string[]} tags
 */

/**
 * @param {"tongue" | "face"} mode
 * @param {Object} data
 * @returns {AnalysisModel | null}
 */
export function fromAnalysisModel(mode, data) {
  if (!data || typeof data !== 'object') return null;
  let model;
  switch (mode) {
    case 'tongue':
      model = fromTongueAnalysisModel(data);
      break;
    case 'face':
      model = fromFaceAnalysisModel(data);
      break;
  }
  return model;
}

/**
 * @param {Object} data
 * @returns {AnalysisModel}
 */
function fromTongueAnalysisModel(data) {
  const exception = [];
  const fromTongueException = fromAnalysisException(exception);
  const c1 = data.upImg || data.tongueImgUrl;
  const c2 = data.downImg || data.tongueBackImgUrl;
  return {
    table: {
      columns: ['舌象维度', '检测结果', '标准值'],
      data: [
        fromTongueException(data.tongueColor, '舌色'),
        fromTongueException(data.tongueCoatingColor, '苔色'),
        fromTongueException(data.tongueShape, '舌形'),
        fromTongueException(data.tongueCoating, '苔质'),
        fromTongueException(data.bodyFluid, '津液'),
        fromTongueException(data.sublingualVein, '舌下'),
      ],
    },
    exception,
    exceptionGroup: [],
    result: data.tongueAnalysisResult || data.tongue || '',
    cover: Object.assign([c1, c2].filter(Boolean), {
      ['舌上']: c1,
      ['舌下']: c2,
    }),
  };
}

/**
 * @param {Object} data
 * @returns {AnalysisModel}
 */
function fromFaceAnalysisModel(data) {
  const exception = [];
  const fromFaceException = fromAnalysisException(exception, (label, value) => `${label}${value}`);
  const c1 = data.faceImg || data.faceImgUrl;
  const c2 = data.faceLeft || data.faceLeftImgUrl;
  const c3 = data.faceRight || data.faceRightImgUrl;
  return {
    table: {
      columns: ['面象维度', '检测结果', '标准值'],
      data: [
        fromFaceException(data.faceColor, '面色'),
        fromFaceException(data.mainColor, '主色'),
        fromFaceException(data.shine, '光泽'),
        fromFaceException(data.leftBlackEye, '左黑眼圈'),
        fromFaceException(data.rightBlackEye, '右黑眼圈'),
        fromFaceException(data.lipColor, '唇色'),
        fromFaceException(data.eyeContact, '眼神'),
        fromFaceException(data.leftEyeColor, '左目色'),
        fromFaceException(data.rightEyeColor, '右目色'),
        fromFaceException(data.hecticCheek, '两颧红'),
        fromFaceException(data.noseFold, '鼻褶'),
        fromFaceException(data.cyanGlabella, '眉间/鼻柱青色'),
        fromFaceException(data.faceSkinDefects, '面部皮损'),
      ],
    },
    exception,
    exceptionGroup: [],
    result: data.faceAnalysisResult || data.face || '',
    cover: Object.assign([c1, c2, c3].filter(Boolean), {
      ['正面']: c1,
      ['左面']: c2,
      ['右面']: c3,
    }),
  };
}

/**
 * @param {AnalysisException[]} exception
 * @param {Function=} $title
 * @returns {Function}
 */
function fromAnalysisException(exception, $title = (label, value) => value) {
  return function (data, label) {
    if (!data || typeof data !== 'object') data = {actualList: [], standardValue: ''};

    const rowProps = {exception: false, invalid: false};

    const standard = data.standardValue || '';
    const values = Array.isArray(data.actualList) ? data.actualList.map(item => {
      const props = {
        value: item.actualValue || '',
        exception: null, invalid: false,
      }
      const suffix = item.contrast || 's';
      if (props.value.endsWith('不符合检测要求')) {
        props.invalid = rowProps.invalid = true;
      } else if (suffix !== 's') {
        if (suffix !== 'r') props.value += ` (${suffix || ''}) `;
        rowProps.exception = true;
        props.exception = {
          title: $title(label, props.value),
          cover: item.splitImage,
          descriptions: [
            item.features ? {label: '【特征】', value: item.features} : null,
            item.clinicalSignificance ? {label: '【临床意义】', value: item.clinicalSignificance} : null,
          ].filter((v) => !!v),
          tags: item.attrs || [],
        }
        exception.push(props.exception);
      }
      return props;
    }) : [];
    return Object.assign([
      [{value: label}],
      values,
      [{value: standard}],
    ], rowProps);
  };
}