/**
 * 文件职责：堂食管理页面纯函数工具。
 * 1. 负责克隆、排序、格式化、校验等纯逻辑。
 * 2. 负责批量编号预览与冲突检测。
 */
import type {
  DineInAreaDto,
  DineInBasicSettingsDto,
  DineInTableDto,
  DineInTableStatus,
} from '#/api/store-dinein';
import type {
  DineInAreaFormState,
  DineInBatchFormState,
  DineInSettingsSnapshot,
  DineInTableFormState,
} from '#/views/store/dine-in/types';

/** 深拷贝堂食设置。 */
export function cloneBasicSettings(source: DineInBasicSettingsDto) {
  return { ...source };
}

/** 深拷贝区域列表。 */
export function cloneAreas(source: DineInAreaDto[]) {
  return source.map((item) => ({ ...item }));
}

/** 深拷贝桌位列表。 */
export function cloneTables(source: DineInTableDto[]) {
  return source.map((item) => ({ ...item, tags: [...item.tags] }));
}

/** 组装设置快照。 */
export function createSettingsSnapshot(payload: {
  areas: DineInAreaDto[];
  basicSettings: DineInBasicSettingsDto;
  tables: DineInTableDto[];
}): DineInSettingsSnapshot {
  return {
    basicSettings: cloneBasicSettings(payload.basicSettings),
    areas: cloneAreas(payload.areas),
    tables: cloneTables(payload.tables),
  };
}

/** 按排序字段与名称稳定排序区域。 */
export function sortAreas(source: DineInAreaDto[]) {
  return cloneAreas(source).toSorted((a, b) => {
    const sortDiff = a.sort - b.sort;
    if (sortDiff !== 0) return sortDiff;
    return a.name.localeCompare(b.name);
  });
}

/** 按编号排序桌位。 */
export function sortTables(source: DineInTableDto[]) {
  return cloneTables(source).toSorted((a, b) => a.code.localeCompare(b.code));
}

/** 规范化桌位编号（大写 + 去空格）。 */
export function normalizeTableCode(code: string) {
  return code.trim().toUpperCase();
}

/** 统计区域下桌位数量。 */
export function countAreaTables(areaId: string, tables: DineInTableDto[]) {
  return tables.filter((item) => item.areaId === areaId).length;
}

/** 根据状态计算样式 class。 */
export function resolveStatusClassName(status: DineInTableStatus) {
  return `status-${status}`;
}

/** 批量生成编号预览。 */
export function generateBatchCodes(payload: {
  codePrefix: string;
  count: number;
  startNumber: number;
}) {
  const prefix = payload.codePrefix.trim().toUpperCase() || 'A';
  const start = Math.max(1, Math.floor(payload.startNumber));
  const count = Math.max(1, Math.min(50, Math.floor(payload.count)));
  const width = Math.max(String(start + count - 1).length, 2);

  return Array.from({ length: count }).map((_, index) => {
    const codeNumber = String(start + index).padStart(width, '0');
    return `${prefix}${codeNumber}`;
  });
}

/** 校验区域表单。 */
export function validateAreaForm(payload: {
  areaId?: string;
  areas: DineInAreaDto[];
  form: DineInAreaFormState;
}) {
  if (!payload.form.name.trim()) return '请输入区域名称';
  if (payload.form.sort <= 0) return '排序必须大于 0';

  const duplicated = payload.areas.some((item) => {
    if (payload.areaId && item.id === payload.areaId) return false;
    return item.name.trim() === payload.form.name.trim();
  });
  if (duplicated) return '区域名称已存在，请更换';

  return '';
}

/** 校验桌位表单。 */
export function validateTableForm(payload: {
  form: DineInTableFormState;
  tableId?: string;
  tables: DineInTableDto[];
}) {
  const code = normalizeTableCode(payload.form.code);
  if (!code) return '请输入桌位编号';
  if (!payload.form.areaId) return '请选择所属区域';
  if (payload.form.seats <= 0) return '座位数必须大于 0';

  const duplicated = payload.tables.some((item) => {
    if (payload.tableId && item.id === payload.tableId) return false;
    return item.code === code;
  });
  if (duplicated) return '桌位编号已存在，请更换';

  return '';
}

/** 校验批量生成表单。 */
export function validateBatchForm(payload: {
  existingCodes: string[];
  form: DineInBatchFormState;
}) {
  if (!payload.form.areaId) return '请选择所属区域';
  if (!payload.form.codePrefix.trim()) return '请输入编号前缀';
  if (payload.form.startNumber <= 0) return '起始编号必须大于 0';
  if (payload.form.count <= 0 || payload.form.count > 50)
    return '生成数量范围为 1-50';
  if (payload.form.seats <= 0) return '座位数必须大于 0';

  const generatedCodes = generateBatchCodes(payload.form);
  const existingSet = new Set(
    payload.existingCodes.map((item) => item.toUpperCase()),
  );
  const conflictCode = generatedCodes.find((code) => existingSet.has(code));
  if (conflictCode) return `桌位编号 ${conflictCode} 已存在，请调整后重试`;

  return '';
}
