import type { QualityComponentDefinition, QualityProps } from '../core/types';

import { parseColumnSpec } from '../core/column-spec';
import { cssStyle, escapeHtml } from '../core/html';
import { QUALITY_ICONS } from '../core/icons';
import { QUALITY_CATEGORY } from '../core/types';

/** 样品信息默认展示的字段，值全部来自报告上下文 */
const SAMPLE_FIELDS: { expr: string; label: string }[] = [
  { label: '样品编号', expr: '{{report.sampleNo}}' },
  { label: '产品名称', expr: '{{report.productName}}' },
  { label: '规格型号', expr: '{{report.spec}}' },
  { label: '批次号', expr: '{{report.batchNo}}' },
  { label: '检验日期', expr: '{{report.inspectDate}}' },
  { label: '检验员', expr: '{{report.inspector}}' },
];

const CELL_BORDER = '1px solid #d9d9d9';

function textOf(value: unknown): string {
  return String(value ?? '').trim();
}

/**
 * 出表用的字段：填了 fields 就整块照它来，否则用默认字段。
 * <p>
 * 与分组检验项表共用同一套 `字段名=绑定表达式` 语法（见 {@link parseColumnSpec}），
 * 免得同一个「键值对列表」长出两种写法。合并标记 `#` 在这里没有意义，解析出来也只是被丢掉，
 * 所以 validate 里明确拦下，不让用户以为自己写对了。
 */
function effectiveFields(properties: QualityProps): { expr: string; label: string }[] {
  const custom = parseColumnSpec(textOf(properties.fields));
  return custom.items.length > 0
    ? custom.items.map((field) => ({ label: field.label, expr: field.expr }))
    : SAMPLE_FIELDS;
}

function buildRows(
  pairsPerRow: number,
  showBorder: boolean,
  fields: { expr: string; label: string }[],
): string {
  const perRow = Math.max(pairsPerRow, 1);
  const border = showBorder ? CELL_BORDER : 'none';
  const rows: string[] = [];
  for (let index = 0; index < fields.length; index += perRow) {
    const rowFields = fields.slice(index, index + perRow);
    // 末行凑不满一组时，让最后一个值格横向吃掉余下的列。照原样铺满格子的话，
    // 右侧会秃出几个只有边框的空格（字段数不是「每行组数」整数倍时必然出现）。
    const tailColspan = rowFields.length < perRow ? (perRow - rowFields.length) * 2 + 1 : 1;
    const cells = rowFields
      .map((field, position) => {
        const span = position === rowFields.length - 1 && tailColspan > 1 ? ` colspan="${tailColspan}"` : '';
        return (
          `<td style="${cssStyle({
            border,
            padding: '5px 8px',
            background: '#fafafa',
            'font-weight': 600,
            width: '90px',
          })}">${escapeHtml(field.label)}</td>` +
          `<td${span} style="${cssStyle({ border, padding: '5px 8px' })}">${escapeHtml(field.expr)}</td>`
        );
      })
      .join('');
    rows.push(`<tr>${cells}</tr>`);
  }
  return rows.join('');
}

export const sampleInfoDefinition: QualityComponentDefinition = {
  type: 'SampleInfo',
  name: 'sampleInfo',
  label: '样品信息',
  category: QUALITY_CATEGORY.HEADER,
  icon: QUALITY_ICONS.sample,
  aiHint: '样品与物料的基本信息块：产品名称、规格、批号、数量、生产日期、有效日期等键值对。',
  defaults: { title: '样品信息', pairsPerRow: 2, showBorder: true },
  propertySchema: [
    { key: 'title', label: '区块标题', type: 'string', defaultValue: '样品信息' },
    {
      key: 'pairsPerRow',
      label: '每行字段数',
      type: 'number',
      defaultValue: 2,
      tip: '一行放几组「字段名 + 值」',
    },
    { key: 'showBorder', label: '显示边框', type: 'boolean', defaultValue: true },
    {
      key: 'fields',
      label: '字段定义（覆盖默认字段）',
      type: 'text',
      tip:
        '留空则用默认的六项。格式：字段名=绑定表达式，多项用 | 分隔，' +
        '如 样品编号={{report.sampleNo}}|产品名称={{report.productName}}|生产日期={{report.produceDate}}。' +
        '每行放几组仍由上面的「每行字段数」控制；这里不支持 # 合并标记',
    },
  ],
  dataSchema: SAMPLE_FIELDS.map((field) => ({
    // 表达式形如 {{report.sampleNo}}，去掉两层花括号即绑定路径
    key: field.expr.slice(2, -2),
    label: field.label,
    type: 'string' as const,
    bindable: true,
  })),
  buildContent: (properties) => {
    const rawTitle = String(properties.title ?? '').trim();
    const heading = rawTitle
      ? `<div style="${cssStyle({
          'font-size': '13px',
          'font-weight': 600,
          margin: '0 0 4px',
        })}">${escapeHtml(rawTitle)}</div>`
      : '';
    const table = `<table style="${cssStyle({
      width: '100%',
      'border-collapse': 'collapse',
      'font-size': '12px',
    })}">${buildRows(
      Number(properties.pairsPerRow ?? 2),
      properties.showBorder !== false,
      effectiveFields(properties),
    )}</table>`;
    return {
      tagName: 'div',
      components: heading + table,
      style: { margin: '0 0 10px' },
    };
  },
  validate: (properties) => {
    const parsed = parseColumnSpec(textOf(properties.fields));
    const errors = [...parsed.errors];
    if (parsed.items.some((field) => field.merge)) {
      errors.push(
        '样品信息的「字段定义」不支持 # 合并标记（那是分组检验项表标组名用的），请去掉字段名前的 #',
      );
    }
    return errors;
  },
};
