import {
  FAILURE_SUPPLEMENT_FIELDS,
  getRequiredSupplementFields,
  type StandardizationFailureItem,
} from '@/services/standardizedService';

const PRINT_WINDOW_FEATURES = 'popup,width=1024,height=768,resizable,scrollbars';
const PRINT_READY_TIMEOUT_MS = 1500;

type FailureSupplementDownloadReason = 'popup-blocked' | 'print-unavailable' | 'print-failed';

export type FailureSupplementExportResult =
  | { mode: 'print'; count: number }
  | { mode: 'download'; count: number; filename: string; reason: FailureSupplementDownloadReason };

function escapeHtml(value: unknown) {
  return String(value ?? '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

function getSuggestionText(item: StandardizationFailureItem) {
  const hint = item.human_fix_hint?.trim();
  return hint || '请补充标 * 的字段';
}

function renderFailureCard(item: StandardizationFailureItem) {
  const requiredFields = getRequiredSupplementFields({
    missing_required_fields: item.missing_required_fields,
    failure_reason: item.failure_reason,
    human_fix_hint: item.human_fix_hint,
  });
  const requiredKeys = new Set(requiredFields.filter((field) => field.required).map((field) => field.key));
  const title = item.original_name || item.standardized_name || '未命名物料';

  return `
    <section class="supplement-card">
      <h1>${escapeHtml(title)}</h1>
      <div class="suggestion">
        <div class="suggestion-label">补充建议</div>
        <div class="suggestion-text">${escapeHtml(getSuggestionText(item))}</div>
      </div>
      <div class="field-list">
        ${FAILURE_SUPPLEMENT_FIELDS.map((field) => `
          <div class="field-row">
            <div class="field-label">
              ${escapeHtml(field.label)}${requiredKeys.has(field.key) ? '<span class="required">*</span>' : ''}
            </div>
            <div class="handwrite-area"></div>
          </div>
        `).join('')}
      </div>
    </section>
  `;
}

export function buildFailureSupplementPrintHtml(items: StandardizationFailureItem[]) {
  const cards = items.map(renderFailureCard).join('\n');

  return `<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>标准化失败补充卡</title>
  <style>
    * {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      color: #111827;
      background: #f8fafc;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      line-height: 1.5;
    }

    main {
      max-width: 920px;
      margin: 0 auto;
      padding: 24px;
    }

    .supplement-card {
      break-inside: avoid;
      page-break-inside: avoid;
      margin: 0 0 20px;
      border: 1px solid #cbd5e1;
      background: #fff;
      padding: 18px;
    }

    h1 {
      margin: 0 0 14px;
      font-size: 24px;
      font-weight: 700;
      letter-spacing: 0;
      overflow-wrap: anywhere;
    }

    .suggestion {
      margin-bottom: 16px;
      border: 2px solid #f59e0b;
      background: #fffbeb;
      padding: 12px;
    }

    .suggestion-label {
      margin-bottom: 4px;
      color: #92400e;
      font-size: 13px;
      font-weight: 700;
    }

    .suggestion-text {
      color: #78350f;
      font-size: 16px;
      font-weight: 650;
      white-space: pre-wrap;
      overflow-wrap: anywhere;
    }

    .field-list {
      display: grid;
      gap: 10px;
    }

    .field-row {
      display: grid;
      grid-template-columns: 8.5rem minmax(0, 1fr);
      min-height: 58px;
      border: 1px solid #d1d5db;
    }

    .field-label {
      display: flex;
      align-items: center;
      min-width: 0;
      border-right: 1px solid #d1d5db;
      padding: 10px 12px;
      font-size: 15px;
      font-weight: 650;
      overflow-wrap: anywhere;
    }

    .required {
      margin-left: 4px;
      color: #dc2626;
      font-weight: 800;
    }

    .handwrite-area {
      min-height: 58px;
      background-image: linear-gradient(to bottom, transparent 27px, #e5e7eb 28px, transparent 29px);
      background-size: 100% 29px;
    }

    .signature-page {
      display: flex;
      min-height: 72vh;
      break-before: page;
      page-break-before: always;
      flex-direction: column;
      justify-content: center;
      gap: 48px;
      background: #fff;
      padding: 56px 64px;
      border: 1px solid #cbd5e1;
      font-size: 22px;
      font-weight: 650;
    }

    .signature-line {
      min-height: 54px;
      border-bottom: 1px solid #111827;
      white-space: pre;
    }

    @page {
      margin: 14mm;
    }

    @media print {
      body {
        background: #fff;
      }

      main {
        max-width: none;
        padding: 0;
      }

      .supplement-card {
        margin-bottom: 10mm;
      }
    }
  </style>
</head>
<body>
  <main>
    ${cards}
    <section class="signature-page">
      <div class="signature-line">负责人（签字）：</div>
      <div class="signature-line">盖                章：</div>
    </section>
  </main>
</body>
</html>`;
}

function sanitizeFilenamePart(value: string) {
  return value
    .trim()
    .replace(/[\\/:*?"<>|]+/g, '-')
    .replace(/\s+/g, '-')
    .replace(/-+/g, '-')
    .replace(/^-|-$/g, '')
    .slice(0, 48);
}

function buildFailureSupplementDownloadFilename(items: StandardizationFailureItem[]) {
  const firstItemName = sanitizeFilenamePart(items[0]?.original_name || items[0]?.standardized_name || '失败补充卡');
  const batchIds = [...new Set(items.map((item) => item.batch_id).filter(Boolean))];
  const batchPart = batchIds.length === 1 ? sanitizeFilenamePart(batchIds[0]) : `${batchIds.length || 1}批次`;
  const timestamp = new Date().toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, '');

  return `${firstItemName || '失败补充卡'}-${batchPart}-${timestamp}.html`;
}

function downloadFailureSupplementHtml(items: StandardizationFailureItem[], html: string) {
  const filename = buildFailureSupplementDownloadFilename(items);
  const blob = new Blob([html], { type: 'text/html;charset=utf-8' });

  if (!window.URL?.createObjectURL) {
    throw new Error('当前浏览器不支持生成补充卡文件，请换用 Chrome 或 Edge 后重试。');
  }

  const url = window.URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  link.rel = 'noopener';
  document.body.appendChild(link);
  link.click();
  link.remove();
  window.setTimeout(() => window.URL.revokeObjectURL(url), 0);

  return filename;
}

function waitForPrintDocument(printWindow: Window) {
  return new Promise<void>((resolve) => {
    if (printWindow.document.readyState === 'complete') {
      resolve();
      return;
    }

    let settled = false;
    const timeoutId = window.setTimeout(finish, PRINT_READY_TIMEOUT_MS);
    function finish() {
      if (settled) {
        return;
      }
      settled = true;
      printWindow.removeEventListener('load', finish);
      window.clearTimeout(timeoutId);
      resolve();
    }

    printWindow.addEventListener('load', finish, { once: true });
  });
}

function downloadFallback(
  items: StandardizationFailureItem[],
  html: string,
  reason: FailureSupplementDownloadReason,
): FailureSupplementExportResult {
  return {
    mode: 'download',
    count: items.length,
    filename: downloadFailureSupplementHtml(items, html),
    reason,
  };
}

export async function openFailureSupplementPrintView(items: StandardizationFailureItem[]): Promise<FailureSupplementExportResult> {
  if (items.length === 0) {
    throw new Error('当前没有可下载的失败记录。');
  }

  const html = buildFailureSupplementPrintHtml(items);
  const printWindow = window.open('', '_blank', PRINT_WINDOW_FEATURES);
  if (!printWindow) {
    try {
      return downloadFallback(items, html, 'popup-blocked');
    } catch (err) {
      throw new Error(`浏览器阻止了打印窗口，且补充卡文件生成失败：${err instanceof Error ? err.message : String(err)}`);
    }
  }

  printWindow.document.open();
  printWindow.document.write(html);
  printWindow.document.close();
  printWindow.focus();

  if (typeof printWindow.print !== 'function') {
    printWindow.close();
    return downloadFallback(items, html, 'print-unavailable');
  }

  await waitForPrintDocument(printWindow);

  try {
    printWindow.print();
    return { mode: 'print', count: items.length };
  } catch {
    printWindow.close();
    return downloadFallback(items, html, 'print-failed');
  }
}
