import * as ExcelJS from 'exceljs';
import type { CellValue } from './imports.types';

export function parseJson<T>(raw: string | null | undefined): T | null {
  if (!raw) return null;
  try {
    return JSON.parse(raw) as T;
  } catch {
    return null;
  }
}

export function textValue(value: CellValue): string {
  if (value === null || value === undefined) return '';
  return String(value).trim();
}

export function normalizeHeader(value: string): string {
  return value
    .trim()
    .toLowerCase()
    .replace(/[\s（）()]/g, '');
}

export function headerMatches(header: string, alias: string): boolean {
  const h = normalizeHeader(header);
  const a = normalizeHeader(alias);
  if (!h || !a) return false;
  return h === a || h.includes(a) || a.includes(h);
}

export function cellValue(cell: ExcelJS.Cell | undefined): CellValue {
  if (!cell) return null;
  const value = cell.value;
  if (value === null || value === undefined) return null;
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
    return value;
  }
  if (value instanceof Date) return value;
  if (typeof value === 'object') {
    const candidate = value as { text?: unknown; result?: unknown };
    if (typeof candidate.text === 'string') return candidate.text;
    if (typeof candidate.result === 'string' || typeof candidate.result === 'number') {
      return candidate.result;
    }
    if (candidate.result instanceof Date) return candidate.result;
  }
  return null;
}

export function parseDateValue(value: CellValue): string | null {
  if (value instanceof Date && !Number.isNaN(value.getTime())) {
    return value.toISOString().slice(0, 10);
  }
  const raw = textValue(value);
  if (!raw) return null;
  const match = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2})/.exec(raw);
  if (!match) return null;
  const year = Number(match[1]);
  const month = Number(match[2]);
  const day = Number(match[3]);
  const date = new Date(Date.UTC(year, month - 1, day));
  if (
    date.getUTCFullYear() !== year ||
    date.getUTCMonth() !== month - 1 ||
    date.getUTCDate() !== day
  ) {
    return null;
  }
  return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
}

export function safeError(error: unknown): string {
  if (error instanceof Error) return error.message.slice(0, 120);
  return '未知错误';
}

export function applyString(target: object, key: string, value: CellValue): void {
  const text = textValue(value);
  if (text) (target as Record<string, unknown>)[key] = text;
}

export function optionalNumber(value: CellValue): number | null {
  const text = textValue(value);
  if (!text) return null;
  const parsed = Number(text);
  return Number.isFinite(parsed) ? parsed : null;
}

export function csvCell(value: string): string {
  return `"${value.replace(/"/g, '""')}"`;
}
