/**
 * monitor-types-dns-ssl smoke (2026-05-30): DNS + SSL monitor types are
 * wired end-to-end.
 *
 * Re-adds the 'dns' type (removed in audit2-17f for having no strategy) with
 * a real Node dns/promises implementation, and adds an 'ssl' cert-watch type
 * using Node's tls module. This static smoke asserts the full wiring so a
 * future refactor can't half-ship them the way 'dns' was the first time:
 *
 *   - strategy files exist and export the expected class
 *   - engine registry maps 'dns' + 'ssl' to those strategies
 *   - Zod create schema accepts both types
 *   - create service has type-specific host/port handling
 *   - UI dropdown lists both options
 *   - unit tests exist for both strategies
 */
import './_lib';
import { ok, fail } from './_lib';
import { readFileSync, existsSync } from 'fs';
import path from 'path';

const ROOT = path.resolve(__dirname, '../..');

function read(rel: string): string {
    const abs = path.join(ROOT, rel);
    if (!existsSync(abs)) fail(`read ${rel}`, `not found`);
    return readFileSync(abs, 'utf8');
}

function assertPresent(label: string, src: string, needle: string | RegExp): void {
    const re = typeof needle === 'string'
        ? new RegExp(needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
        : needle;
    if (!re.test(src)) fail(label, `missing pattern: ${String(needle)}`);
    ok(label);
}

function main(): void {
    // Strategies exist.
    const dns = read('src/lib/monitor-strategies/dns.strategy.ts');
    assertPresent('dns: exports DnsMonitorStrategy', dns, /export class DnsMonitorStrategy implements MonitorStrategy/);
    assertPresent('dns: uses Node dns/promises (no new dep)', dns, /from 'dns\/promises'/);
    assertPresent('dns: resolves A/AAAA/CNAME/MX/TXT', dns, /resolveCname[\s\S]+resolveMx[\s\S]+resolveTxt/);

    const ssl = read('src/lib/monitor-strategies/ssl.strategy.ts');
    assertPresent('ssl: exports SslMonitorStrategy', ssl, /export class SslMonitorStrategy implements MonitorStrategy/);
    assertPresent('ssl: uses Node tls module (no new dep)', ssl, /await import\('tls'\)/);
    assertPresent('ssl: honours tlsExpiryWarningDays', ssl, /tlsExpiryWarningDays/);
    assertPresent('ssl: goes through the SSRF guard', ssl, /resolveAndValidate/);

    // Engine registry dispatches both.
    const engine = read('src/lib/monitor-engine.ts');
    assertPresent('engine: registers dns strategy', engine, /'dns':\s*new DnsMonitorStrategy\(\)/);
    assertPresent('engine: registers ssl strategy', engine, /'ssl':\s*new SslMonitorStrategy\(\)/);
    assertPresent('engine: passes tlsExpiryWarningDays into MonitorForCheck', engine, /tlsExpiryWarningDays: monitor\.tlsExpiryWarningDays/);

    // Zod accepts both.
    const schema = read('src/lib/validations/monitor.schema.ts');
    assertPresent('zod: type enum includes dns', schema, /'dns'/);
    assertPresent('zod: type enum includes ssl', schema, /'ssl'/);

    // Create service host/port handling.
    const service = read('src/lib/services/monitor.service.ts');
    assertPresent('service: dns host handling', service, /validated\.type === 'dns'/);
    assertPresent('service: ssl host + 443 default', service, /validated\.type === 'ssl'/);

    // UI dropdown.
    const ui = read('src/components/monitors/AddMonitorModal.tsx');
    assertPresent('ui: DNS option', ui, /<option value="dns">/);
    assertPresent('ui: SSL option', ui, /<option value="ssl">/);

    // Unit tests exist.
    if (!existsSync(path.join(ROOT, 'src/lib/monitor-strategies/__tests__/dns.strategy.test.ts'))) {
        fail('tests: dns strategy test', 'not found');
    }
    ok('tests: dns strategy test present');
    if (!existsSync(path.join(ROOT, 'src/lib/monitor-strategies/__tests__/ssl.strategy.test.ts'))) {
        fail('tests: ssl strategy test', 'not found');
    }
    ok('tests: ssl strategy test present');

    ok('monitor-types-dns-ssl', 'dns + ssl wired end-to-end: strategy + engine + zod + service + UI + tests');
}

main();
