import crypto from 'node:crypto';
import { existsSync, readFileSync, statSync } from 'node:fs';
import { readFile } from 'node:fs/promises';
import http from 'node:http';
import path from 'node:path';
import { fileURLToPath, domainToASCII } from 'node:url';
import {
  authenticateUser,
  approveUser,
  claimLegacyData,
  createApiToken,
  createAccountToken,
  createDomain,
  createUserWithAccountToken,
  consumeAccountToken,
  deleteApiToken,
  deleteDnsCredential,
  deleteDomain,
  deleteSmtpCredential,
  getAdminResourceInventory,
  getAdminUser,
  getDnsCredential,
  getDomain,
  getDomainByName,
  getSendAnalytics,
  getSettings,
  getDefaultSmtpRelay,
  getSmtpRelay,
  getSmtpCredential,
  getSystemEmailSettings,
  getUser,
  getUserByLogin,
  initDatabase,
  invalidateAccountTokens,
  listApiTokens,
  listAuditLogs,
  listDnsCredentials,
  listDomains,
  listSendEvents,
  listSmtpCredentials,
  listSmtpRelays,
  listUsersWithResourceCounts,
  logAudit,
  logSendEvent,
  markUserEmailVerified,
  previewUserMerge,
  saveDnsCredential,
  saveDomainStatus,
  saveSettings,
  saveSmtpRelay,
  saveSmtpCredential,
  saveSystemEmailSettings,
  seedAdminUser,
  seedSmtpCredential,
  deleteSmtpRelay,
  transferApiTokens,
  transferDnsCredential,
  transferDomain,
  updateDkim,
  updateDomain,
  updateUser,
  executeUserMerge,
  verifyApiToken,
  verifyUserCredentials
} from './db.js';
import { applyDnsSetup, testDnsCredential } from './dns-providers.js';
import { startDnsAutoChecker } from './dns-auto-checker.js';
import { startPostfixDeliveryTracker } from './delivery-tracker.js';
import { buildDnsGuide, buildSystemDnsChecks } from './dns-guide.js';
import { createDkimKeyPair } from './dkim.js';
import {
  buildMessage,
  domainFromAddress,
  extractAddress,
  parseAddressList,
  sendViaSmtp,
  signMessageForDomain
} from './mailer.js';
import {
  parseSubmissionListeners,
  publicSubmissionListeners,
  startSubmissionServer
} from './submission.js';
import {
  buildPasswordResetEmail,
  buildVerificationEmail,
  sendSystemEmail
} from './system-mail.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
loadDotEnv();

const envConfig = {
  port: Number(process.env.PORT || 3000),
  dataDir: process.env.DATA_DIR || path.join(process.cwd(), 'data'),
  adminUser: process.env.ADMIN_USER || 'admin',
  adminEmail: process.env.ADMIN_EMAIL || `${process.env.ADMIN_USER || 'admin'}@mailhub.local`,
  adminPassword: process.env.ADMIN_PASSWORD || 'change-this-admin-password',
  legacyApiToken: process.env.API_TOKEN || '',
  smtpHost: process.env.SMTP_HOST || '',
  smtpPort: Number(process.env.SMTP_PORT || 25),
  smtpSecure: String(process.env.SMTP_SECURE || '').toLowerCase() === 'true',
  smtpUser: process.env.SMTP_USERNAME || '',
  smtpPassword: process.env.SMTP_PASSWORD || '',
  smtpHelo: process.env.SMTP_HELO || process.env.MAIL_HOSTNAME || 'mailhub.local',
  postfixLogFile: process.env.POSTFIX_LOG_FILE || path.join(process.env.DATA_DIR || path.join(process.cwd(), 'data'), 'postfix-logs', 'mail.log'),
  postfixLogPollIntervalMs: Number(process.env.POSTFIX_LOG_POLL_INTERVAL_MS || 5000),
  deliveryTrackingEnabled: String(process.env.DELIVERY_TRACKING_ENABLED || 'true').toLowerCase() !== 'false',
  dnsAutoCheckEnabled: String(process.env.DNS_AUTO_CHECK_ENABLED || 'true').toLowerCase() !== 'false',
  dnsAutoCheckIntervalMs: Number(process.env.DNS_AUTO_CHECK_INTERVAL_MS || 60000),
  dnsAutoCheckLimit: Number(process.env.DNS_AUTO_CHECK_LIMIT || 25),
  submissionEnabled: String(process.env.SUBMISSION_ENABLED || 'true').toLowerCase() !== 'false',
  submissionHost: process.env.SUBMISSION_HOST || process.env.APP_BASE_URL?.replace(/^https?:\/\//, '') || 'localhost',
  submissionListeners: parseSubmissionListeners(process.env.SUBMISSION_PORTS),
  submissionUsername: process.env.SUBMISSION_USERNAME || '',
  submissionPassword: process.env.SUBMISSION_PASSWORD || '',
  submissionAllowInsecureAuth: String(process.env.SUBMISSION_ALLOW_INSECURE_AUTH || '').toLowerCase() === 'true',
  submissionTlsCert: process.env.SUBMISSION_TLS_CERT || '',
  submissionTlsKey: process.env.SUBMISSION_TLS_KEY || '',
  sessionSecret: process.env.SESSION_SECRET || crypto
    .createHash('sha256')
    .update(`${process.env.ADMIN_PASSWORD || 'change-this-admin-password'}:${process.env.API_TOKEN || ''}`)
    .digest('hex')
};

const defaultSettings = {
  appBaseUrl: process.env.APP_BASE_URL || 'http://127.0.0.1:3000',
  mailHostname: process.env.MAIL_HOSTNAME || 'mailhub.local',
  sendingIp: process.env.SENDING_IP || '',
  defaultSpfMechanisms: process.env.DEFAULT_SPF_MECHANISMS || 'include:spf.mailjet.com',
  dmarcPolicy: process.env.DMARC_POLICY || 'none',
  dmarcRua: process.env.DMARC_RUA || '',
  sendRequiresVerified: String(process.env.SEND_REQUIRES_VERIFIED || '').toLowerCase() === 'true' ? 'true' : 'false'
};

const emailVerificationPurpose = 'email_verification';
const passwordResetPurpose = 'password_reset';

initDatabase(envConfig.dataDir, envConfig.sessionSecret);
const admin = seedAdminUser({
  username: envConfig.adminUser,
  email: envConfig.adminEmail,
  password: envConfig.adminPassword
});
claimLegacyData(admin.id);
seedSmtpCredential(admin.id, envConfig.submissionUsername, envConfig.submissionPassword);

startPostfixDeliveryTracker({
  enabled: envConfig.deliveryTrackingEnabled,
  logFile: envConfig.postfixLogFile,
  pollIntervalMs: envConfig.postfixLogPollIntervalMs
});

startDnsAutoChecker({
  enabled: envConfig.dnsAutoCheckEnabled,
  intervalMs: envConfig.dnsAutoCheckIntervalMs,
  limit: envConfig.dnsAutoCheckLimit
});

const server = http.createServer(async (req, res) => {
  try {
    setSecurityHeaders(res);
    if (req.method === 'OPTIONS') return handleOptions(res);
    const url = new URL(req.url, `http://${req.headers.host || 'localhost'}`);
    if (url.pathname === '/healthz') return sendJson(res, 200, { ok: true });
    if (req.method === 'POST' && (url.pathname === '/api/register' || url.pathname === '/register')) return await handleRegister(req, res);
    if (req.method === 'POST' && (url.pathname === '/api/login' || url.pathname === '/login')) return await handleLogin(req, res);
    if (req.method === 'POST' && url.pathname === '/api/logout') return handleLogout(res);
    if (url.pathname === '/api/auth/verify-email') return await handleVerifyEmail(req, res, url);
    if (req.method === 'POST' && url.pathname === '/api/auth/resend-verification') return await handleResendVerification(req, res);
    if (req.method === 'POST' && url.pathname === '/api/auth/forgot-password') return await handleForgotPassword(req, res);
    if (req.method === 'POST' && url.pathname === '/api/auth/reset-password') return await handleResetPassword(req, res);

    const user = getRequestUser(req, url.pathname);
    if (isLoginAsset(url.pathname)) {
      if ((url.pathname === '/login' || url.pathname === '/register') && user) return redirect(res, '/');
      return await serveStatic(req, res, url);
    }

    if (!user) {
      if (url.pathname.startsWith('/api/')) return sendJson(res, 401, { error: 'Authentication required.' });
      return redirect(res, '/login');
    }

    if (url.pathname.startsWith('/api/')) return await handleApi(req, res, url, user);
    return await serveStatic(req, res, url);
  } catch (error) {
    console.error(error);
    return sendJson(res, 500, { error: error.message || 'Internal server error.' });
  }
});

server.listen(envConfig.port, '0.0.0.0', () => {
  console.log(`MailHub listening on 0.0.0.0:${envConfig.port}`);
});

startSubmissionServer({
  enabled: envConfig.submissionEnabled,
  listeners: envConfig.submissionListeners,
  hostname: envConfig.submissionHost,
  allowInsecureAuth: envConfig.submissionAllowInsecureAuth,
  tlsCertPath: envConfig.submissionTlsCert,
  tlsKeyPath: envConfig.submissionTlsKey,
  relayHost: envConfig.smtpHost,
  relayPort: envConfig.smtpPort,
  relaySecure: envConfig.smtpSecure,
  relayUsername: envConfig.smtpUser,
  relayPassword: envConfig.smtpPassword,
  relayHelo: envConfig.smtpHelo
});

async function handleApi(req, res, url, user) {
  const method = req.method || 'GET';
  const pathname = url.pathname;

  if (method === 'GET' && pathname === '/api/me') {
    return sendJson(res, 200, { user });
  }
  if (method === 'GET' && pathname === '/api/config') {
    return sendJson(res, 200, publicConfig(user));
  }
  if (method === 'GET' && pathname === '/api/domains') {
    return sendJson(res, 200, { domains: listDomains(user.id) });
  }
  if (method === 'POST' && pathname === '/api/domains') {
    const body = await readJson(req);
    const settings = runtimeSettings();
    const domain = normalizeDomain(body.domain);
    if (!domain) return sendJson(res, 400, { error: '域名格式不正确。' });
    const selector = normalizeSelector(body.selector || defaultSelector());
    if (!selector) return sendJson(res, 400, { error: 'DKIM selector 格式不正确。' });
    const dnsCredentialId = Number(body.dnsCredentialId || 0) || null;
    if (dnsCredentialId && !getDnsCredential(dnsCredentialId, user.id)) {
      return sendJson(res, 400, { error: 'DNS 凭据不存在。' });
    }
    const smtpRelayId = Number(body.smtpRelayId || 0) || null;
    if (smtpRelayId && !getSmtpRelay(smtpRelayId, user.id)) {
      return sendJson(res, 400, { error: 'SMTP 出口不存在。' });
    }
    const keys = createDkimKeyPair();
    try {
      const row = createDomain(user.id, {
        domain,
        selector,
        dnsCredentialId,
        smtpRelayId,
        verificationToken: crypto.randomBytes(18).toString('hex'),
        dkimPublic: keys.publicKey,
        dkimPrivate: keys.privateKey,
        senderHost: normalizeHostname(body.senderHost || settings.mailHostname),
        sendingIp: String(body.sendingIp || settings.sendingIp).trim(),
        spfExtra: String(body.spfExtra ?? settings.defaultSpfMechanisms).trim(),
        dmarcPolicy: normalizeDmarcPolicy(body.dmarcPolicy || settings.dmarcPolicy),
        dmarcRua: String(body.dmarcRua ?? settings.dmarcRua).trim()
      });
      return sendJson(res, 201, { domain: row });
    } catch (error) {
      if (isUniqueError(error)) return sendJson(res, 409, { error: '该域名已被添加。' });
      throw error;
    }
  }
  if (method === 'GET' && pathname === '/api/events') {
    return sendJson(res, 200, { events: listSendEvents(user.id) });
  }
  if (method === 'GET' && pathname === '/api/analytics') {
    return sendJson(res, 200, { analytics: getSendAnalytics(user.id, { days: Number(url.searchParams.get('days') || 30) }) });
  }
  if (method === 'GET' && pathname === '/api/smtp-credential') {
    return sendJson(res, 200, { credential: getSmtpCredential(user.id, { includePassword: true }) });
  }
  if ((method === 'POST' || method === 'PUT' || method === 'PATCH') && pathname === '/api/smtp-credential') {
    const body = await readJson(req);
    try {
      const current = getSmtpCredential(user.id);
      saveSmtpCredential(user.id, {
        id: current?.id || null,
        username: String(body.username || '').trim(),
        password: String(body.password || '')
      });
    } catch (error) {
      if (isUniqueError(error)) return sendJson(res, 409, { error: 'SMTP 用户名已被占用。' });
      throw error;
    }
    return sendJson(res, 200, { credential: getSmtpCredential(user.id, { includePassword: true }) });
  }
  if (method === 'GET' && pathname === '/api/smtp-credentials') {
    return sendJson(res, 200, { credentials: listSmtpCredentials(user.id, { includePassword: true }) });
  }
  if (method === 'POST' && pathname === '/api/smtp-credentials') {
    const body = await readJson(req);
    try {
      const credential = saveSmtpCredential(user.id, {
        username: String(body.username || '').trim(),
        password: String(body.password || '')
      });
      return sendJson(res, 201, { credential: getSmtpCredential(credential.id, user.id, { includePassword: true }) });
    } catch (error) {
      if (isUniqueError(error)) return sendJson(res, 409, { error: 'SMTP 用户名已被占用。' });
      throw error;
    }
  }
  const smtpCredentialMatch = pathname.match(/^\/api\/smtp-credentials\/(\d+)$/);
  if (smtpCredentialMatch) {
    const id = Number(smtpCredentialMatch[1]);
    if (method === 'GET') {
      const credential = getSmtpCredential(id, user.id, { includePassword: true });
      return sendJson(res, credential ? 200 : 404, { credential });
    }
    if (method === 'PATCH' || method === 'PUT') {
      const body = await readJson(req);
      try {
        const credential = saveSmtpCredential(user.id, {
          id,
          username: String(body.username || '').trim(),
          password: String(body.password || '')
        });
        return sendJson(res, credential ? 200 : 404, {
          credential: credential ? getSmtpCredential(credential.id, user.id, { includePassword: true }) : null
        });
      } catch (error) {
        if (isUniqueError(error)) return sendJson(res, 409, { error: 'SMTP 用户名已被占用。' });
        throw error;
      }
    }
    if (method === 'DELETE') {
      const deleted = deleteSmtpCredential(id, user.id);
      return sendJson(res, deleted ? 200 : 404, { deleted });
    }
  }
  if (method === 'GET' && pathname === '/api/smtp-relays') {
    return sendJson(res, 200, { relays: listSmtpRelays(user.id) });
  }
  if (method === 'POST' && pathname === '/api/smtp-relays') {
    const body = await readJson(req);
    const relay = saveSmtpRelay(user.id, smtpRelayPatch(body));
    return sendJson(res, 201, { relay });
  }
  const smtpRelayMatch = pathname.match(/^\/api\/smtp-relays\/(\d+)$/);
  if (smtpRelayMatch) {
    const id = Number(smtpRelayMatch[1]);
    if (method === 'GET') {
      const relay = getSmtpRelay(id, user.id, { includePassword: true });
      return sendJson(res, relay ? 200 : 404, { relay });
    }
    if (method === 'PATCH' || method === 'PUT') {
      const body = await readJson(req);
      const relay = saveSmtpRelay(user.id, { ...smtpRelayPatch(body), id });
      return sendJson(res, relay ? 200 : 404, { relay });
    }
    if (method === 'DELETE') {
      const deleted = deleteSmtpRelay(id, user.id);
      return sendJson(res, deleted ? 200 : 404, { deleted });
    }
  }
  if (method === 'POST' && pathname === '/api/send') {
    const body = await readJson(req);
    const smtpRelayId = Number(body.smtpRelayId || 0) || null;
    if (smtpRelayId && !getSmtpRelay(smtpRelayId, user.id)) {
      return sendJson(res, 400, { error: 'SMTP 出口不存在。' });
    }
    const result = await sendMailFromBody(body, user);
    return sendJson(res, 202, result);
  }

  if (method === 'GET' && pathname === '/api/api-tokens') {
    return sendJson(res, 200, { tokens: listApiTokens(user.id) });
  }
  if (method === 'POST' && pathname === '/api/api-tokens') {
    const body = await readJson(req);
    return sendJson(res, 201, { token: createApiToken(user.id, body.name) });
  }
  const tokenMatch = pathname.match(/^\/api\/api-tokens\/(\d+)$/);
  if (tokenMatch && method === 'DELETE') {
    const deleted = deleteApiToken(Number(tokenMatch[1]), user.id);
    return sendJson(res, deleted ? 200 : 404, { deleted });
  }

  if (method === 'GET' && pathname === '/api/dns-credentials') {
    return sendJson(res, 200, { credentials: listDnsCredentials(user.id) });
  }
  if (method === 'POST' && pathname === '/api/dns-credentials') {
    const body = await readJson(req);
    const credential = saveDnsCredential(user.id, body);
    return sendJson(res, 201, { credential });
  }
  const dnsMatch = pathname.match(/^\/api\/dns-credentials\/(\d+)(?:\/([a-z-]+))?$/);
  if (dnsMatch) {
    const id = Number(dnsMatch[1]);
    const action = dnsMatch[2] || '';
    if ((method === 'PUT' || method === 'PATCH') && !action) {
      const body = await readJson(req);
      const credential = saveDnsCredential(user.id, { ...body, id });
      return sendJson(res, credential ? 200 : 404, { credential });
    }
    if (method === 'DELETE' && !action) {
      const deleted = deleteDnsCredential(id, user.id);
      return sendJson(res, deleted ? 200 : 404, { deleted });
    }
    if (method === 'POST' && action === 'test') {
      const credential = getDnsCredential(id, user.id, { includeCredentials: true });
      if (!credential) return sendJson(res, 404, { error: 'DNS 凭据不存在。' });
      const result = await testDnsCredential(credential);
      return sendJson(res, result.ok ? 200 : 400, result);
    }
  }

  if (pathname.startsWith('/api/admin/')) {
    return await handleAdminApi(req, res, url, user);
  }

  const domainMatch = pathname.match(/^\/api\/domains\/(\d+)(?:\/([a-z-]+))?$/);
  if (domainMatch) {
    const id = Number(domainMatch[1]);
    const action = domainMatch[2] || '';
    if (method === 'GET' && !action) {
      const domain = getDomain(id, { userId: user.id });
      if (!domain) return sendJson(res, 404, { error: '域名不存在。' });
      return sendJson(res, 200, { domain });
    }
    if (method === 'PATCH' && !action) {
      const body = await readJson(req);
      const dnsCredentialId = body.dnsCredentialId !== undefined ? Number(body.dnsCredentialId || 0) || null : undefined;
      if (dnsCredentialId && !getDnsCredential(dnsCredentialId, user.id)) {
        return sendJson(res, 400, { error: 'DNS 凭据不存在。' });
      }
      const smtpRelayId = body.smtpRelayId !== undefined ? Number(body.smtpRelayId || 0) || null : undefined;
      if (smtpRelayId && !getSmtpRelay(smtpRelayId, user.id)) {
        return sendJson(res, 400, { error: 'SMTP 出口不存在。' });
      }
      const row = updateDomain(id, user.id, {
        selector: body.selector ? normalizeSelector(body.selector) : undefined,
        dnsCredentialId,
        smtpRelayId,
        senderHost: body.senderHost ? normalizeHostname(body.senderHost) : undefined,
        sendingIp: body.sendingIp !== undefined ? String(body.sendingIp).trim() : undefined,
        spfExtra: body.spfExtra !== undefined ? String(body.spfExtra).trim() : undefined,
        dmarcPolicy: body.dmarcPolicy ? normalizeDmarcPolicy(body.dmarcPolicy) : undefined,
        dmarcRua: body.dmarcRua !== undefined ? String(body.dmarcRua).trim() : undefined
      });
      if (!row) return sendJson(res, 404, { error: '域名不存在。' });
      return sendJson(res, 200, { domain: row });
    }
    if (method === 'DELETE' && !action) {
      const deleted = deleteDomain(id, user.id);
      return sendJson(res, deleted ? 200 : 404, { deleted });
    }
    if (method === 'POST' && action === 'check') {
      const row = getDomain(id, { userId: user.id });
      if (!row) return sendJson(res, 404, { error: '域名不存在。' });
      const guide = await buildDnsGuide(row);
      saveDomainStatus(id, user.id, guide);
      return sendJson(res, 200, { guide, domain: getDomain(id, { userId: user.id }) });
    }
    if (method === 'POST' && action === 'apply-dns') {
      const row = getDomain(id, { userId: user.id, includePrivate: true });
      if (!row) return sendJson(res, 404, { error: '域名不存在。' });
      const credentialId = Number(row.dnsCredentialId || 0);
      const credential = credentialId ? getDnsCredential(credentialId, user.id, { includeCredentials: true }) : null;
      if (!credential) return sendJson(res, 400, { error: '请先为该域名绑定 DNS API 凭据。' });
      const guide = await buildDnsGuide(row);
      const applyResult = await applyDnsSetup(row, credential, guide);
      const checkedGuide = await buildDnsGuideAfterApply(row, applyResult);
      checkedGuide.apply = applyResult;
      saveDomainStatus(id, user.id, checkedGuide);
      return sendJson(res, applyResult.ok ? 200 : 207, {
        apply: applyResult,
        guide: checkedGuide,
        domain: getDomain(id, { userId: user.id })
      });
    }
    if (method === 'POST' && action === 'rotate-dkim') {
      const row = getDomain(id, { userId: user.id });
      if (!row) return sendJson(res, 404, { error: '域名不存在。' });
      const body = await readJson(req).catch(() => ({}));
      const selector = normalizeSelector(body.selector || defaultSelector());
      const next = updateDkim(id, user.id, createDkimKeyPair(), selector);
      return sendJson(res, 200, { domain: next });
    }
    if (method === 'POST' && action === 'test-send') {
      const row = getDomain(id, { userId: user.id });
      if (!row) return sendJson(res, 404, { error: '域名不存在。' });
      const body = await readJson(req);
      const smtpRelayId = Number(body.smtpRelayId || 0) || null;
      if (smtpRelayId && !getSmtpRelay(smtpRelayId, user.id)) {
        return sendJson(res, 400, { error: 'SMTP 出口不存在。' });
      }
      const from = body.from || `noreply@${row.domain}`;
      const result = await sendMailFromBody({
        from,
        to: body.to,
        subject: body.subject || `MailHub test for ${row.domain}`,
        text: body.text || `This is a MailHub test message from ${row.domain}.`,
        smtpRelayId: body.smtpRelayId
      }, user);
      return sendJson(res, 202, result);
    }
  }

  return sendJson(res, 404, { error: 'Not found.' });
}

async function handleAdminApi(req, res, url, user) {
  const method = req.method || 'GET';
  const pathname = url.pathname;
  if (!pathname.startsWith('/api/admin/')) return null;
  if (user.role !== 'admin') return sendJson(res, 403, { error: '需要管理员权限。' });
  if (method === 'GET' && pathname === '/api/admin/settings') {
    return sendJson(res, 200, { settings: await adminRuntimeSettings() });
  }
  if (method === 'GET' && pathname === '/api/admin/system-email') {
    return sendJson(res, 200, { settings: getSystemEmailSettings() });
  }
  if (method === 'GET' && pathname === '/api/admin/audit-logs') {
    return sendJson(res, 200, { logs: listAuditLogs(adminAuditFilters(url.searchParams)) });
  }
  if (method === 'GET' && pathname === '/api/admin/resources') {
    return sendJson(res, 200, { inventory: getAdminResourceInventory() });
  }
  const transferDomainMatch = pathname.match(/^\/api\/admin\/resources\/domains\/(\d+)\/transfer$/);
  if (transferDomainMatch && method === 'POST') {
    const body = await readJson(req);
    try {
      const domain = transferDomain({
        actorUserId: user.id,
        domainId: Number(transferDomainMatch[1]),
        targetUserId: body.targetUserId,
        dnsCredentialMode: body.dnsCredentialMode
      });
      return sendJson(res, 200, { domain });
    } catch (error) {
      return sendAdminTransferError(res, error);
    }
  }
  const transferDnsCredentialMatch = pathname.match(/^\/api\/admin\/resources\/dns-credentials\/(\d+)\/transfer$/);
  if (transferDnsCredentialMatch && method === 'POST') {
    const body = await readJson(req);
    try {
      const credential = transferDnsCredential({
        actorUserId: user.id,
        credentialId: Number(transferDnsCredentialMatch[1]),
        targetUserId: body.targetUserId
      });
      return sendJson(res, 200, { credential });
    } catch (error) {
      return sendAdminTransferError(res, error);
    }
  }
  if (method === 'POST' && pathname === '/api/admin/resources/api-tokens/transfer') {
    const body = await readJson(req);
    try {
      const tokens = transferApiTokens({
        actorUserId: user.id,
        tokenIds: body.tokenIds,
        targetUserId: body.targetUserId
      });
      return sendJson(res, 200, { tokens });
    } catch (error) {
      return sendAdminTransferError(res, error);
    }
  }
  if (method === 'POST' && pathname === '/api/admin/migrations/user-merge/preview') {
    const body = await readJson(req);
    try {
      const preview = previewUserMerge({
        sourceUserId: body.sourceUserId,
        targetUserId: body.targetUserId
      });
      return sendJson(res, 200, { preview });
    } catch (error) {
      return sendAdminMigrationError(res, error);
    }
  }
  if (method === 'POST' && pathname === '/api/admin/migrations/user-merge/execute') {
    const body = await readJson(req);
    try {
      const result = executeUserMerge({
        actorUserId: user.id,
        sourceUserId: body.sourceUserId,
        targetUserId: body.targetUserId,
        options: body.options,
        confirmation: body.confirmation
      });
      return sendJson(res, 200, { result });
    } catch (error) {
      return sendAdminMigrationError(res, error);
    }
  }
  if ((method === 'PATCH' || method === 'PUT') && pathname === '/api/admin/system-email') {
    const body = await readJson(req);
    const settings = saveSystemEmailSettings({
      host: body.host,
      port: body.port,
      secure: body.secure,
      username: body.username,
      password: body.password,
      helo: body.helo,
      fromEmail: body.fromEmail,
      fromName: body.fromName,
      testRecipient: body.testRecipient
    });
    logAudit({
      actorUserId: user.id,
      action: 'admin.update_system_email',
      targetType: 'system_email',
      targetId: 'default',
      summary: settings
    });
    return sendJson(res, 200, { settings });
  }
  if (method === 'POST' && pathname === '/api/admin/system-email/test') {
    const body = await readJson(req).catch(() => ({}));
    const settings = systemMailSettingsForSend();
    const to = extractAddress(body.to || settings.testRecipient);
    if (!to) return sendJson(res, 400, { error: '测试收件人地址格式不正确。' });
    const result = await sendSystemEmail(settings, {
      to,
      subject: 'MailHub 系统邮件测试',
      text: '这是一封 MailHub 系统邮件测试。'
    });
    logAudit({
      actorUserId: user.id,
      action: 'admin.test_system_email',
      targetType: 'system_email',
      targetId: 'default',
      summary: {
        to,
        ok: result.ok,
        message: result.message,
        queueId: result.queueId
      }
    });
    return sendJson(res, result.ok ? 202 : 502, { result });
  }
  if ((method === 'PATCH' || method === 'PUT') && pathname === '/api/admin/settings') {
    const body = await readJson(req);
    saveSettings({
      appBaseUrl: body.appBaseUrl,
      mailHostname: body.mailHostname,
      sendingIp: body.sendingIp,
      defaultSpfMechanisms: body.defaultSpfMechanisms,
      dmarcPolicy: normalizeDmarcPolicy(body.dmarcPolicy),
      dmarcRua: body.dmarcRua,
      sendRequiresVerified: boolString(body.sendRequiresVerified)
    });
    return sendJson(res, 200, { settings: await adminRuntimeSettings() });
  }
  if (method === 'GET' && pathname === '/api/admin/users') {
    return sendJson(res, 200, { users: listUsersWithResourceCounts() });
  }
  const approveMatch = pathname.match(/^\/api\/admin\/users\/(\d+)\/approve$/);
  if (approveMatch && method === 'POST') {
    const current = getUser(Number(approveMatch[1]));
    if (!current) return sendJson(res, 404, { error: '用户不存在。' });
    if (current.status === 'pending_email') return sendJson(res, 400, { error: '用户尚未验证邮箱。' });
    if (current.status !== 'pending_review') return sendJson(res, 400, { error: '只能审批等待审核的用户。' });
    const target = approveUser(current.id);
    if (!target) return sendJson(res, 404, { error: '用户不存在。' });
    logAudit({
      actorUserId: user.id,
      action: 'admin.approve_user',
      targetType: 'user',
      targetId: String(target.id),
      targetUserId: target.id,
      summary: {
        username: target.username,
        status: target.status
      }
    });
    return sendJson(res, 200, { user: target });
  }
  const resendVerificationMatch = pathname.match(/^\/api\/admin\/users\/(\d+)\/resend-verification$/);
  if (resendVerificationMatch && method === 'POST') {
    const target = getUser(Number(resendVerificationMatch[1]));
    if (!target) return sendJson(res, 404, { error: '用户不存在。' });
    if (target.status !== 'pending_email') return sendJson(res, 400, { error: '用户不需要重新发送验证邮件。' });
    const result = await createAndSendVerificationEmail(target);
    logAudit({
      actorUserId: user.id,
      action: 'admin.resend_verification',
      targetType: 'user',
      targetId: String(target.id),
      targetUserId: target.id,
      summary: {
        username: target.username,
        email: target.email,
        verificationEmailSent: result.ok,
        message: result.message,
        queueId: result.queueId
      }
    });
    return sendJson(res, 202, verificationEmailResponse(result));
  }
  const passwordResetMatch = pathname.match(/^\/api\/admin\/users\/(\d+)\/password-reset$/);
  if (passwordResetMatch && method === 'POST') {
    const target = getUser(Number(passwordResetMatch[1]));
    if (!target) return sendJson(res, 404, { error: '用户不存在。' });
    const result = await createAndSendPasswordResetEmail(target);
    logAudit({
      actorUserId: user.id,
      action: 'admin.password_reset',
      targetType: 'user',
      targetId: String(target.id),
      targetUserId: target.id,
      summary: {
        username: target.username,
        email: target.email,
        ok: result.ok,
        message: result.message,
        queueId: result.queueId
      }
    });
    return sendJson(res, result.ok ? 202 : 502, { result });
  }
  const temporaryPasswordMatch = pathname.match(/^\/api\/admin\/users\/(\d+)\/temporary-password$/);
  if (temporaryPasswordMatch && method === 'POST') {
    const target = getUser(Number(temporaryPasswordMatch[1]));
    if (!target) return sendJson(res, 404, { error: '用户不存在。' });
    const body = await readJson(req);
    let updated;
    try {
      updated = updateUser(target.id, { password: body.password });
    } catch (error) {
      if (error?.message === '密码至少需要 8 位。') return sendJson(res, 400, { error: error.message });
      throw error;
    }
    logAudit({
      actorUserId: user.id,
      action: 'admin.temporary_password',
      targetType: 'user',
      targetId: String(target.id),
      targetUserId: target.id,
      summary: {
        username: target.username,
        email: target.email,
        passwordSet: true
      }
    });
    return sendJson(res, 200, { user: updated });
  }
  const userMatch = pathname.match(/^\/api\/admin\/users\/(\d+)$/);
  if (userMatch && method === 'PATCH') {
    const body = await readJson(req);
    let updated;
    try {
      updated = updateUser(Number(userMatch[1]), {
        role: body.role,
        status: body.status,
        password: body.password
      });
    } catch (error) {
      if (['用户状态不正确。', '密码至少需要 8 位。'].includes(error?.message)) {
        return sendJson(res, 400, { error: error.message });
      }
      throw error;
    }
    return sendJson(res, updated ? 200 : 404, { user: updated });
  }
  return sendJson(res, 404, { error: 'Not found.' });
}

function adminAuditFilters(searchParams) {
  const requested = {
    actorUserId: auditUserIdParam(searchParams.get('actorUserId'), { allowSystem: true }),
    targetUserId: auditUserIdParam(searchParams.get('targetUserId')),
    action: auditTextParam(searchParams.get('action')),
    from: auditDateParam(searchParams.get('from')),
    to: auditDateParam(searchParams.get('to'))
  };
  return Object.fromEntries(
    ['actorUserId', 'targetUserId', 'action', 'from', 'to']
      .filter((key) => requested[key] !== undefined)
      .map((key) => [key, requested[key]])
  );
}

function sendAdminTransferError(res, error) {
  if (['域名不存在。', 'DNS 凭据不存在。', 'API Token 不存在。'].includes(error?.message)) {
    return sendJson(res, 404, { error: error.message });
  }
  if (['目标用户不可用。', 'DNS 凭据归属不一致。'].includes(error?.message)) {
    return sendJson(res, 400, { error: error.message });
  }
  throw error;
}

function sendAdminMigrationError(res, error) {
  if (['源用户不存在。'].includes(error?.message)) return sendJson(res, 404, { error: error.message });
  if ([
    '目标用户不可用。',
    '源用户和目标用户不能相同。',
    '确认文本不匹配。'
  ].includes(error?.message)) {
    return sendJson(res, 400, { error: error.message });
  }
  throw error;
}

function auditUserIdParam(value, { allowSystem = false } = {}) {
  if (value === null) return undefined;
  const text = String(value).trim();
  if (!text) return undefined;
  if (allowSystem && ['system', 'null'].includes(text.toLowerCase())) return null;
  return /^[1-9]\d*$/.test(text) ? Number(text) : undefined;
}

function auditTextParam(value) {
  const text = String(value || '').trim();
  return text || undefined;
}

function auditDateParam(value) {
  const text = String(value || '').trim();
  if (!text) return undefined;
  const dateOnly = text.match(/^(\d{4})-(\d{2})-(\d{2})$/);
  if (dateOnly) {
    const year = Number(dateOnly[1]);
    const month = Number(dateOnly[2]);
    const day = Number(dateOnly[3]);
    const date = new Date(Date.UTC(year, month - 1, day));
    if (
      date.getUTCFullYear() === year &&
      date.getUTCMonth() === month - 1 &&
      date.getUTCDate() === day
    ) {
      return date.toISOString();
    }
    return undefined;
  }
  if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(text)) return undefined;
  const date = new Date(text);
  return !Number.isNaN(date.getTime()) && date.toISOString() === text ? text : undefined;
}

async function sendMailFromBody(body, user) {
  const settings = runtimeSettings();
  const from = extractAddress(body.from);
  if (!from) throw new Error('发件人地址格式不正确。');
  const recipients = parseAddressList(body.to);
  if (!recipients.length) throw new Error('收件人地址格式不正确。');
  const fromDomain = domainFromAddress(from);
  const domain = getDomainByName(fromDomain, { userId: user.id, includePrivate: true });
  if (!domain) throw new Error(`发件域名 ${fromDomain} 不属于当前用户或尚未添加。`);
  if (settings.sendRequiresVerified && !domain.status?.verified) {
    throw new Error(`发件域名 ${fromDomain} 尚未完成验证。`);
  }

  const rawMessage = buildMessage({
    from,
    to: recipients,
    subject: body.subject || '(no subject)',
    text: body.text || '',
    html: body.html || '',
    baseUrl: settings.appBaseUrl
  });
  const signed = signMessageForDomain(rawMessage, domain);
  const smtpTransport = smtpTransportForSend(body, domain, user);
  try {
    const smtpResult = await sendViaSmtp({
      host: smtpTransport.host,
      port: smtpTransport.port,
      secure: smtpTransport.secure,
      username: smtpTransport.username,
      password: smtpTransport.password,
      helo: smtpTransport.helo,
      mailFrom: from,
      recipients,
      rawMessage: signed
    });
    logSendEvent({
      userId: user.id,
      domainId: domain.id,
      smtpRelayId: smtpTransport.smtpRelayId,
      sender: from,
      recipients,
      subject: body.subject || '(no subject)',
      status: 'queued',
      detail: smtpResult.message,
      queueId: smtpResult.queueId,
      deliveryLog: smtpResult.deliveryLog
    });
    return {
      queued: true,
      domain: domain.domain,
      recipients,
      smtp: smtpResult.message,
      queueId: smtpResult.queueId,
      smtpRelayId: smtpTransport.smtpRelayId
    };
  } catch (error) {
    logSendEvent({
      userId: user.id,
      domainId: domain.id,
      smtpRelayId: smtpTransport.smtpRelayId,
      sender: from,
      recipients,
      subject: body.subject || '(no subject)',
      status: 'failed',
      detail: error.message,
      deliveryLog: deliveryLogFromError(error)
    });
    throw error;
  }
}

function deliveryLogFromError(error) {
  if (Array.isArray(error?.deliveryLog)) return error.deliveryLog;
  return [{
    at: new Date().toISOString(),
    phase: 'error',
    direction: 'system',
    message: error?.message || 'Unknown SMTP delivery error',
    ok: false
  }];
}

function smtpTransportForSend(body, domain, user) {
  const requestedRelayId = Number(body.smtpRelayId || 0) || null;
  if (requestedRelayId) {
    const relay = getSmtpRelay(requestedRelayId, user.id, { includePassword: true });
    if (!relay) throw new Error('SMTP 出口不存在。');
    return smtpTransportFromRelay(relay);
  }
  if (domain.smtpRelayId) {
    const relay = getSmtpRelay(domain.smtpRelayId, user.id, { includePassword: true });
    if (!relay) throw new Error('SMTP 出口不存在。');
    return smtpTransportFromRelay(relay);
  }
  const defaultRelay = getDefaultSmtpRelay(user.id, { includePassword: true });
  if (defaultRelay) return smtpTransportFromRelay(defaultRelay);
  return {
    smtpRelayId: null,
    host: envConfig.smtpHost,
    port: envConfig.smtpPort,
    secure: envConfig.smtpSecure,
    username: envConfig.smtpUser,
    password: envConfig.smtpPassword,
    helo: envConfig.smtpHelo
  };
}

function smtpTransportFromRelay(relay) {
  return {
    smtpRelayId: relay.id,
    host: relay.host,
    port: relay.port,
    secure: relay.secure,
    username: relay.username,
    password: relay.password || '',
    helo: relay.helo || envConfig.smtpHelo
  };
}

function runBackground(promise) {
  promise.catch((error) => console.error(error));
}

async function handleRegister(req, res) {
  const body = await readJson(req);
  try {
    const { user, accountToken } = createUserWithAccountToken({
      username: body.username,
      email: body.email,
      password: body.password,
      status: 'pending_email'
    }, emailVerificationPurpose, { ttlMinutes: 24 * 60 });
    const emailResult = await sendVerificationEmail(user, accountToken.token);
    return sendRegisterSuccess(req, res, user, emailResult);
  } catch (error) {
    if (isUniqueError(error)) return sendAuthError(req, res, 409, '用户名或邮箱已被注册。', '/register');
    return sendAuthError(req, res, 400, error.message || '注册失败。', '/register');
  }
}

async function handleResendVerification(req, res) {
  const body = await readJson(req);
  const user = getUserByLogin(body.email);
  if (user?.status === 'pending_email') {
    runBackground(createAndSendVerificationEmail(user));
  }
  return sendJson(res, 202, publicVerificationResendResponse());
}

async function handleForgotPassword(req, res) {
  const body = await readJson(req);
  const user = getUserByLogin(body.email);
  if (user) runBackground(createAndSendPasswordResetEmail(user));
  return sendJson(res, 202, publicForgotPasswordResponse());
}

async function handleResetPassword(req, res) {
  const body = await readJson(req);
  if (String(body.password || '').length < 8) return sendJson(res, 400, { error: '密码至少需要 8 位。' });
  const consumed = consumeAccountToken(body.token, passwordResetPurpose);
  if (!consumed) return sendJson(res, 400, { error: '重置链接无效或已过期。' });
  updateUser(consumed.userId, { password: body.password });
  return sendJson(res, 200, { message: '密码已重置，请使用新密码登录。' });
}

async function handleVerifyEmail(req, res, url) {
  if ((req.method || 'GET') !== 'GET') return sendJson(res, 404, { error: 'Not found.' });
  const token = String(url.searchParams.get('token') || '').trim();
  if (!token) return sendJson(res, 400, { error: '验证链接无效或已过期。' });
  const consumed = consumeAccountToken(token, emailVerificationPurpose);
  if (!consumed) return sendJson(res, 400, { error: '验证链接无效或已过期。' });
  const user = markUserEmailVerified(consumed.userId);
  if (!user) return sendJson(res, 400, { error: '验证链接无效或已过期。' });
  return sendJson(res, 200, {
    user,
    message: '邮箱验证成功，请等待管理员审核。'
  });
}

async function createAndSendVerificationEmail(user) {
  const settings = systemMailSettingsForSend();
  if (!systemMailConfigured(settings)) return { ok: false, message: '系统邮件未配置。' };
  invalidateAccountTokens(user.id, emailVerificationPurpose);
  const accountToken = createAccountToken(user.id, emailVerificationPurpose, { ttlMinutes: 24 * 60 });
  const result = await sendVerificationEmailWithSettings(user, accountToken.token, settings);
  if (!result.ok) invalidateAccountTokens(user.id, emailVerificationPurpose);
  return result;
}

async function createAndSendPasswordResetEmail(user) {
  const settings = systemMailSettingsForSend();
  if (!systemMailConfigured(settings)) return { ok: false, message: '系统邮件未配置。' };
  invalidateAccountTokens(user.id, passwordResetPurpose);
  const accountToken = createAccountToken(user.id, passwordResetPurpose, { ttlMinutes: 60 });
  const result = await sendSystemEmail(settings, buildPasswordResetEmail({
    appBaseUrl: settings.appBaseUrl,
    to: user.email,
    token: accountToken.token,
    fromEmail: settings.fromEmail,
    fromName: settings.fromName
  }));
  if (!result.ok) invalidateAccountTokens(user.id, passwordResetPurpose);
  return result;
}

async function sendVerificationEmail(user, token) {
  const settings = systemMailSettingsForSend();
  if (!systemMailConfigured(settings)) {
    return { ok: false, message: '系统邮件未配置。' };
  }
  return await sendVerificationEmailWithSettings(user, token, settings);
}

async function sendVerificationEmailWithSettings(user, token, settings) {
  return await sendSystemEmail(settings, buildVerificationEmail({
    appBaseUrl: settings.appBaseUrl,
    to: user.email,
    token,
    fromEmail: settings.fromEmail,
    fromName: settings.fromName
  }));
}

function systemMailConfigured(settings) {
  return Boolean(settings.host && extractAddress(settings.fromEmail));
}

function systemMailSettingsForSend() {
  return {
    ...getSystemEmailSettings({ includeSecret: true }),
    appBaseUrl: runtimeSettings().appBaseUrl
  };
}

function publicVerificationResendResponse() {
  return {
    message: '如果账号需要验证，我们会发送验证邮件。'
  };
}

function publicForgotPasswordResponse() {
  return {
    message: '如果邮箱存在，我们会发送密码重置邮件。'
  };
}

function verificationEmailResponse(result) {
  return {
    verificationEmailSent: Boolean(result.ok),
    message: result.ok ? '验证邮件已发送。' : '验证邮件暂未发送，请稍后重试或联系管理员。',
    result: {
      ok: Boolean(result.ok),
      message: result.message || '',
      queueId: result.queueId || ''
    }
  };
}

async function handleLogin(req, res) {
  const body = await readJson(req);
  const user = verifyUserCredentials(body.username || body.email, body.password);
  if (!user) return sendAuthError(req, res, 401, '账号或密码不正确。', '/login');
  if (user.status !== 'active') return sendAuthError(req, res, 403, loginStatusMessage(user.status), '/login');
  return sendAuthSuccess(req, res, 200, user);
}

function sendRegisterSuccess(req, res, user, emailResult = { ok: false }) {
  const message = emailResult.ok
    ? '注册成功，验证邮件已发送，请先验证邮箱，验证后等待管理员审核。'
    : '注册成功，请先验证邮箱；验证邮件暂未发送，请联系管理员或稍后重试。';
  if (wantsHtmlRedirect(req)) return redirect(res, `/login?error=${encodeURIComponent(message)}`, 303);
  return sendJson(res, 201, {
    user,
    message,
    verificationEmailSent: Boolean(emailResult.ok)
  });
}

function sendAuthSuccess(req, res, status, user) {
  const token = createSessionToken(user);
  const cookie = sessionCookie(token);
  if (wantsHtmlRedirect(req)) return redirect(res, '/', 303, { 'Set-Cookie': cookie });
  res.writeHead(status, {
    'Content-Type': 'application/json; charset=utf-8',
    'Set-Cookie': cookie
  });
  res.end(JSON.stringify({ user }));
}

function sendAuthError(req, res, status, message, fallbackPath) {
  if (wantsHtmlRedirect(req)) return redirect(res, `${fallbackPath}?error=${encodeURIComponent(message)}`, 303);
  return sendJson(res, status, { error: message });
}

function loginStatusMessage(status) {
  if (status === 'pending_email') return '请先验证邮箱。';
  if (status === 'pending_review') return '账号正在等待管理员审核。';
  if (status === 'disabled') return '账号已被禁用。';
  return '账号或密码不正确。';
}

function handleLogout(res) {
  res.writeHead(200, {
    'Content-Type': 'application/json; charset=utf-8',
    'Set-Cookie': 'mailhub_session=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0'
  });
  res.end(JSON.stringify({ ok: true }));
}

function getRequestUser(req, pathname) {
  const sessionUser = getSessionUser(req);
  if (sessionUser) return sessionUser;
  const auth = req.headers.authorization || '';
  if (auth.startsWith('Basic ')) {
    const decoded = Buffer.from(auth.slice(6), 'base64').toString('utf8');
    const index = decoded.indexOf(':');
    const user = authenticateUser(decoded.slice(0, index), decoded.slice(index + 1));
    if (user) return user;
  }
  if (pathname === '/api/send' && auth.startsWith('Bearer ')) {
    const token = auth.slice(7);
    const user = verifyApiToken(token);
    if (user) return user;
    if (envConfig.legacyApiToken && safeEqual(token, envConfig.legacyApiToken)) return getAdminUser();
  }
  return null;
}

function getSessionUser(req) {
  const token = parseCookies(req.headers.cookie || '').mailhub_session;
  if (!token || !token.includes('.')) return null;
  const [payload, signature] = token.split('.');
  if (!payload || !signature || !safeEqual(signature, signSessionPayload(payload))) return null;
  try {
    const data = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
    if (Number(data.exp) <= Date.now()) return null;
    const user = getUser(Number(data.uid));
    return user?.status === 'active' ? user : null;
  } catch {
    return null;
  }
}

function createSessionToken(user) {
  const payload = Buffer.from(JSON.stringify({
    uid: user.id,
    exp: Date.now() + 12 * 60 * 60 * 1000,
    nonce: crypto.randomBytes(10).toString('hex')
  })).toString('base64url');
  return `${payload}.${signSessionPayload(payload)}`;
}

function signSessionPayload(payload) {
  return crypto.createHmac('sha256', envConfig.sessionSecret).update(payload).digest('base64url');
}

function sessionCookie(token) {
  return [`mailhub_session=${token}`, 'Path=/', 'HttpOnly', 'SameSite=Lax', 'Max-Age=43200'].join('; ');
}

function publicConfig(user) {
  const settings = runtimeSettings();
  const smtpCredential = getSmtpCredential(user.id);
  return {
    ...settings,
    smtpHost: envConfig.smtpHost ? 'configured' : '',
    submission: {
      enabled: envConfig.submissionEnabled,
      host: envConfig.submissionHost,
      ports: publicSubmissionListeners(envConfig.submissionListeners),
      username: smtpCredential?.username || '',
      passwordSet: Boolean(smtpCredential?.passwordSet),
      tls: Boolean(envConfig.submissionTlsCert && envConfig.submissionTlsKey),
      requireTlsForAuth: !envConfig.submissionAllowInsecureAuth
    },
    apiTokenSet: Boolean(envConfig.legacyApiToken),
    usingDefaultAdminPassword: user.role === 'admin' && envConfig.adminPassword === 'change-this-admin-password'
  };
}

function runtimeSettings() {
  const settings = getSettings(defaultSettings);
  return {
    appBaseUrl: settings.appBaseUrl,
    mailHostname: settings.mailHostname,
    sendingIp: settings.sendingIp,
    defaultSpfMechanisms: settings.defaultSpfMechanisms,
    dmarcPolicy: normalizeDmarcPolicy(settings.dmarcPolicy),
    dmarcRua: settings.dmarcRua,
    sendRequiresVerified: String(settings.sendRequiresVerified).toLowerCase() === 'true'
  };
}

async function adminRuntimeSettings() {
  const settings = runtimeSettings();
  return {
    ...settings,
    systemChecks: await buildSystemDnsChecks(settings)
  };
}

async function serveStatic(req, res, url) {
  const publicDir = path.join(__dirname, '..', 'public');
  const pathname = decodeURIComponent(resolveStaticPathname(url.pathname));
  const filePath = path.normalize(path.join(publicDir, pathname));
  if (!filePath.startsWith(publicDir) || !existsSync(filePath) || statSync(filePath).isDirectory()) {
    return sendStaticFile(res, path.join(publicDir, 'index.html'));
  }
  return sendStaticFile(res, filePath);
}

async function sendStaticFile(res, filePath) {
  const ext = path.extname(filePath);
  const contentType = {
    '.html': 'text/html; charset=utf-8',
    '.css': 'text/css; charset=utf-8',
    '.js': 'application/javascript; charset=utf-8',
    '.json': 'application/json; charset=utf-8',
    '.svg': 'image/svg+xml'
  }[ext] || 'application/octet-stream';
  res.writeHead(200, { 'Content-Type': contentType });
  res.end(await readFile(filePath));
}

async function readJson(req) {
  const chunks = [];
  for await (const chunk of req) chunks.push(chunk);
  if (!chunks.length) return {};
  const raw = Buffer.concat(chunks).toString('utf8');
  const contentType = String(req.headers['content-type'] || '').toLowerCase();
  if (contentType.includes('application/x-www-form-urlencoded')) {
    return Object.fromEntries(new URLSearchParams(raw).entries());
  }
  return JSON.parse(raw);
}

function sendJson(res, status, payload) {
  res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' });
  res.end(JSON.stringify(payload));
}

function redirect(res, location, status = 302, headers = {}) {
  res.writeHead(status, { ...headers, Location: location });
  res.end();
}

function wantsHtmlRedirect(req) {
  const contentType = String(req.headers['content-type'] || '').toLowerCase();
  const accept = String(req.headers.accept || '').toLowerCase();
  return contentType.includes('application/x-www-form-urlencoded') && accept.includes('text/html');
}

function setSecurityHeaders(res) {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('Referrer-Policy', 'same-origin');
}

function handleOptions(res) {
  res.writeHead(204, {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET,POST,PUT,PATCH,DELETE,OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization'
  });
  res.end();
}

function parseCookies(header) {
  const cookies = {};
  for (const part of String(header || '').split(';')) {
    const index = part.indexOf('=');
    if (index === -1) continue;
    cookies[part.slice(0, index).trim()] = part.slice(index + 1).trim();
  }
  return cookies;
}

function safeEqual(actual, expected) {
  const a = Buffer.from(String(actual || ''));
  const b = Buffer.from(String(expected || ''));
  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(a, b);
}

function normalizeDomain(input) {
  const raw = String(input || '').trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/.*$/, '').replace(/\.$/, '');
  const ascii = domainToASCII(raw);
  if (!ascii || ascii.length > 253) return '';
  if (!/^(?!-)(?:[a-z0-9-]{1,63}\.)+[a-z]{2,63}$/.test(ascii)) return '';
  return ascii;
}

function normalizeHostname(input) {
  return normalizeDomain(input) || String(input || '').trim().toLowerCase();
}

function normalizeSelector(input) {
  const value = String(input || '').trim().toLowerCase();
  return /^[a-z0-9][a-z0-9-]{0,62}$/.test(value) ? value : '';
}

function normalizeDmarcPolicy(input) {
  const value = String(input || '').trim().toLowerCase();
  return ['none', 'quarantine', 'reject'].includes(value) ? value : 'none';
}

function smtpRelayPatch(body) {
  const patch = {};
  for (const key of ['name', 'host', 'port', 'secure', 'username', 'password', 'helo', 'isDefault']) {
    if (Object.hasOwn(body, key)) patch[key] = body[key];
  }
  return patch;
}

function boolString(value) {
  return String(value).toLowerCase() === 'true' || value === true ? 'true' : 'false';
}

function defaultSelector() {
  const d = new Date();
  return `mh${d.getUTCFullYear()}${String(d.getUTCMonth() + 1).padStart(2, '0')}`;
}

async function buildDnsGuideAfterApply(domain, applyResult) {
  const appliedKeys = new Set((applyResult.results || [])
    .filter((result) => result.ok && !result.skipped)
    .map((result) => result.key));
  let guide = await buildDnsGuide(domain);
  for (let attempt = 0; attempt < 2 && hasUnpropagatedAppliedRecords(guide, appliedKeys); attempt += 1) {
    await sleep(1800);
    guide = await buildDnsGuide(domain);
  }
  return markUnpropagatedAppliedRecords(guide, appliedKeys);
}

function hasUnpropagatedAppliedRecords(guide, appliedKeys) {
  return (guide.records || []).some((record) => appliedKeys.has(record.key) && record.status !== 'ok');
}

function markUnpropagatedAppliedRecords(guide, appliedKeys) {
  const records = (guide.records || []).map((record) => {
    if (!appliedKeys.has(record.key) || record.status === 'ok') return record;
    return {
      ...record,
      status: 'pending',
      warnings: [
        ...(record.warnings || []),
        '已提交到 DNS 服务商，正在等待公共 DNS 传播；稍后点击“立即检查”刷新。'
      ]
    };
  });
  return {
    ...guide,
    records,
    warnings: collectGuideWarnings(records)
  };
}

function collectGuideWarnings(records) {
  return records.flatMap((record) => record.warnings || []);
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function isUniqueError(error) {
  return /UNIQUE constraint failed/i.test(String(error?.message || ''));
}

function isLoginAsset(pathname) {
  return pathname.startsWith('/assets/')
    || [
      '/login',
      '/register',
      '/forgot-password',
      '/resend-verification',
      '/reset-password',
      '/login.html',
      '/login.css',
      '/login.js'
    ].includes(pathname);
}

function resolveStaticPathname(pathname) {
  if (pathname === '/') return '/index.html';
  if (['/login', '/register', '/forgot-password', '/resend-verification', '/reset-password'].includes(pathname)) return '/login.html';
  return pathname;
}

function loadDotEnv() {
  const file = path.join(process.cwd(), '.env');
  if (!existsSync(file)) return;
  const lines = readFileSync(file, 'utf8').split(/\r?\n/);
  for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;
    const index = trimmed.indexOf('=');
    if (index === -1) continue;
    const key = trimmed.slice(0, index).trim();
    let value = trimmed.slice(index + 1).trim();
    if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) value = value.slice(1, -1);
    if (!(key in process.env)) process.env[key] = value;
  }
}
