declare const process: { cwd(): string };
declare function require(name: string): {
  readFileSync?: (path: string, encoding: string) => string;
  join?: (...parts: string[]) => string;
};

const { readFileSync } = require("node:fs");
const { join } = require("node:path");

if (!readFileSync || !join) {
  throw new Error("测试运行环境缺少文件读取能力");
}

const css = readFileSync(join(process.cwd(), "src/assets/styles.css"), "utf-8");

const loginVisual = cssBlock(".login-visual");
assertIncludes(loginVisual, "background: var(--surface-soft);");
assertIncludes(loginVisual, "color: var(--text);");
assertNotIncludes(loginVisual, "rgba(var(--primary-rgb), 0.94)");

const ledgerVisual = cssBlock(".ledger-visual");
assertIncludes(ledgerVisual, "background: var(--card);");
assertIncludes(ledgerVisual, "padding: 22px;");

const appearancePanel = cssBlock(".appearance-panel");
assertIncludes(appearancePanel, "width: min(480px, calc(100vw - 20px));");

const primaryFocus = cssBlock(".primary-button:focus-visible");
assertIncludes(primaryFocus, "outline: 0;");
assertIncludes(primaryFocus, "box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.16);");

const tableRows = cssBlock(".data-table tbody tr");
assertIncludes(tableRows, "transition: background var(--motion-duration-fast) ease;");

const realtimeHeaderActions = cssBlock(".realtime-header-actions");
assertIncludes(realtimeHeaderActions, "display: grid;");
assertIncludes(realtimeHeaderActions, "grid-template-columns: minmax(210px, 242px) 140px;");
assertIncludes(realtimeHeaderActions, "align-items: end;");

const realtimeDateField = cssBlock(".realtime-date-field");
assertIncludes(realtimeDateField, "min-width: 0;");

const realtimeOverviewPanel = cssBlock(".realtime-overview-panel");
assertIncludes(realtimeOverviewPanel, "overflow: hidden;");

const realtimeOverviewHeader = cssBlock(".realtime-overview-header");
assertIncludes(realtimeOverviewHeader, "align-items: center;");
assertIncludes(realtimeOverviewHeader, "padding: 12px var(--panel-padding) 10px;");

const realtimeOverviewTitle = cssBlock(".realtime-overview-title");
assertIncludes(realtimeOverviewTitle, "display: flex;");
assertIncludes(realtimeOverviewTitle, "align-items: baseline;");
assertIncludes(realtimeOverviewTitle, "gap: 10px;");

const realtimeOverviewTitleText = cssBlock(".realtime-overview-title h2,\n.realtime-overview-title p");
assertIncludes(realtimeOverviewTitleText, "margin: 0;");

const realtimeOverviewStats = cssBlock(".realtime-overview-stats");
assertIncludes(realtimeOverviewStats, "padding-top: 0;");

const realtimeOverviewNumbers = cssBlock(".realtime-overview-stats .compact-stat strong");
assertIncludes(realtimeOverviewNumbers, "font-size: 24px;");

const realtimeSyncChip = cssBlock(".realtime-sync-chip");
assertIncludes(realtimeSyncChip, "min-width: 96px;");
assertIncludes(realtimeSyncChip, "justify-content: center;");

const realtimeTableFilterBar = cssBlock(".realtime-table-filter-bar");
assertIncludes(realtimeTableFilterBar, "display: grid;");
assertIncludes(realtimeTableFilterBar, "grid-template-columns: minmax(180px, 220px) minmax(240px, 1fr) 78px auto;");
assertIncludes(realtimeTableFilterBar, "align-items: end;");
assertIncludes(realtimeTableFilterBar, "padding: 10px var(--panel-padding);");

const realtimeClearFilter = cssBlock(".realtime-clear-filter");
assertIncludes(realtimeClearFilter, "min-height: var(--control-height);");
assertIncludes(realtimeClearFilter, "width: 78px;");
assertIncludes(realtimeClearFilter, "justify-self: start;");
assertIncludes(realtimeClearFilter, "padding: 0 12px;");
assertIncludes(realtimeClearFilter, "white-space: nowrap;");

const realtimeFilterResult = cssBlock(".realtime-filter-result");
assertIncludes(realtimeFilterResult, "justify-self: end;");

const payrollCompactToolbar = cssBlock(".payroll-compact-toolbar");
assertIncludes(payrollCompactToolbar, "grid-template-columns: minmax(190px, 240px) minmax(0, 1fr) auto;");
assertIncludes(payrollCompactToolbar, "padding: 12px var(--panel-padding);");

const payrollToolbarSummary = cssBlock(".payroll-toolbar-summary");
assertIncludes(payrollToolbarSummary, "grid-template-columns: minmax(110px, 0.7fr) minmax(110px, 0.7fr) minmax(110px, 0.7fr) minmax(270px, 1.45fr);");
assertIncludes(payrollToolbarSummary, "border-inline: 1px solid var(--line-soft);");

const payrollToolbarRangeText = cssBlock(".payroll-toolbar-range strong,\n.payroll-toolbar-range small");
assertIncludes(payrollToolbarRangeText, "overflow: visible;");
assertIncludes(payrollToolbarRangeText, "white-space: normal;");
assertIncludes(payrollToolbarRangeText, "text-overflow: clip;");

const payrollToolbarActions = cssBlock(".payroll-toolbar-actions");
assertIncludes(payrollToolbarActions, "grid-template-columns: repeat(2, 138px);");
assertIncludes(payrollToolbarActions, "justify-content: end;");

const payrollToolbarActionButtons = cssBlock(".payroll-toolbar-actions .primary-button,\n.payroll-toolbar-actions .secondary-button");
assertIncludes(payrollToolbarActionButtons, "min-height: 34px;");
assertIncludes(payrollToolbarActionButtons, "padding: 0 10px;");
assertIncludes(payrollToolbarActionButtons, "font-size: 13px;");

const payrollDetailPanel = cssBlock(".payroll-detail-panel");
assertIncludes(payrollDetailPanel, "border-color: rgba(var(--accent-rgb), 0.2);");
assertIncludes(payrollDetailPanel, "overflow: hidden;");

const payrollDetailHeader = cssBlock(".payroll-detail-header");
assertIncludes(payrollDetailHeader, "grid-template-columns: minmax(0, 1fr) auto;");

const payrollDetailSummary = cssBlock(".payroll-detail-summary");
assertIncludes(payrollDetailSummary, "grid-template-columns: repeat(4, minmax(110px, auto));");

const salaryDetailTable = cssBlock(".salary-detail-table");
assertIncludes(salaryDetailTable, "font-size: 13px;");
assertIncludes(salaryDetailTable, "min-width: 1560px;");

const salarySummaryToolbar = cssBlock(".salary-summary-toolbar");
assertIncludes(salarySummaryToolbar, "grid-template-columns: minmax(220px, 1fr) repeat(3, minmax(140px, 180px));");

const salarySummaryTable = cssBlock(".salary-summary-table");
assertIncludes(salarySummaryTable, "min-width: 860px;");

const salarySummaryTableCells = cssBlock(".salary-summary-table th,\n.salary-summary-table td");
assertIncludes(salarySummaryTableCells, "padding: 12px 14px;");

const salaryDetailDrawer = cssBlock(".salary-detail-drawer");
assertIncludes(salaryDetailDrawer, "grid-template-columns: repeat(4, minmax(0, 1fr));");

const salaryDetailDrawerHeader = cssBlock(".salary-detail-drawer-header");
assertIncludes(salaryDetailDrawerHeader, "grid-column: 1 / -1;");

const salaryDetailCells = cssBlock(".salary-detail-table th,\n.salary-detail-table td");
assertIncludes(salaryDetailCells, "padding: 10px 12px;");

const payrollSecondaryGrid = cssBlock(".payroll-secondary-grid");
assertIncludes(payrollSecondaryGrid, "grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);");

assertNotIncludes(css, ".payroll-workbench {");
assertNotIncludes(css, ".payroll-flow-strip");
assertNotIncludes(css, ".payroll-summary-band");

assertIncludes(css, "@media (max-width: 1320px)");
assertIncludes(css, ".payroll-compact-toolbar {\n    grid-template-columns: 1fr;\n  }");
assertIncludes(css, ".payroll-toolbar-summary {\n    grid-template-columns: repeat(2, minmax(0, 1fr));");
assertIncludes(css, ".payroll-secondary-grid {\n    grid-template-columns: 1fr;\n  }");
assertIncludes(css, ".payroll-toolbar-summary,\n  .payroll-toolbar-actions,\n  .payroll-detail-summary {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n  }");
assertIncludes(css, ".realtime-header-actions {\n    grid-template-columns: 1fr;\n  }");
assertIncludes(css, ".realtime-overview-title {\n    align-items: flex-start;\n    flex-direction: column;");
assertIncludes(css, ".realtime-table-filter-bar {\n    grid-template-columns: 1fr;");
assertNotIncludes(css, ".payroll-command-step");
assertNotIncludes(css, ".payroll-step-index");
assertNotIncludes(css, ".payroll-command-copy");
assertNotIncludes(css, ".payroll-period-row");
assertNotIncludes(css, ".payroll-source-row");
assertNotIncludes(css, ".payroll-source-copy");

function cssBlock(selector: string): string {
  const pattern = new RegExp(`${escapeRegExp(selector)}\\s*\\{([\\s\\S]*?)\\n\\}`, "m");
  const match = css.match(pattern);
  if (!match) {
    throw new Error(`缺少样式块 ${selector}`);
  }
  return match[1];
}

function assertIncludes(content: string, expected: string): void {
  if (!content.includes(expected)) {
    throw new Error(`期望包含 ${expected}`);
  }
}

function assertNotIncludes(content: string, unexpected: string): void {
  if (content.includes(unexpected)) {
    throw new Error(`不应包含 ${unexpected}`);
  }
}

function escapeRegExp(value: string): string {
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
