import type { FastifyRequest } from 'fastify';

import {
  INTEGRATION_MTLS_HEADERS,
  isIntegrationMtlsEnabled,
  normalizeCertificateFingerprint,
  verifyClientCertificateFingerprint,
} from '@hexahost/integration-auth';

export function extractClientCertFingerprint(request: FastifyRequest): string | undefined {
  const headerCandidates = [
    INTEGRATION_MTLS_HEADERS.clientFingerprint,
    'x-ssl-client-sha256',
    'x-ssl-client-fingerprint',
  ];

  for (const header of headerCandidates) {
    const value = request.headers[header];
    if (typeof value === 'string' && value.trim() !== '') {
      return normalizeCertificateFingerprint(value);
    }
  }

  const socket = request.socket as {
    getPeerCertificate?: () => { fingerprint256?: string };
  };

  if (typeof socket.getPeerCertificate === 'function') {
    const certificate = socket.getPeerCertificate();
    if (certificate?.fingerprint256) {
      return normalizeCertificateFingerprint(certificate.fingerprint256);
    }
  }

  return undefined;
}

export function extractClientCertSubject(request: FastifyRequest): string | undefined {
  const value = request.headers[INTEGRATION_MTLS_HEADERS.clientSubject];
  if (typeof value === 'string' && value.trim() !== '') {
    return value.trim();
  }

  const socket = request.socket as {
    getPeerCertificate?: () => { subject?: { CN?: string } };
  };

  if (typeof socket.getPeerCertificate === 'function') {
    const certificate = socket.getPeerCertificate();
    if (certificate?.subject?.CN) {
      return certificate.subject.CN;
    }
  }

  return undefined;
}

export function assertIntegrationMtls(
  request: FastifyRequest,
  expectedFingerprint: string | null | undefined,
): void {
  if (!isIntegrationMtlsEnabled()) {
    return;
  }

  if (!expectedFingerprint) {
    throw new Error('INTEGRATION_MTLS_REQUIRED_BUT_UNREGISTERED');
  }

  const provided = extractClientCertFingerprint(request);
  if (!provided) {
    throw new Error('INTEGRATION_MTLS_CLIENT_CERT_MISSING');
  }

  if (!verifyClientCertificateFingerprint(provided, expectedFingerprint)) {
    throw new Error('INTEGRATION_MTLS_CLIENT_CERT_MISMATCH');
  }
}
