import { NextRequest, NextResponse } from "next/server";
import tls from "tls";

export async function GET(req: NextRequest) {
  const domain = req.nextUrl.searchParams.get("domain")?.trim();
  const portParam = req.nextUrl.searchParams.get("port");
  const port = portParam ? Number(portParam) : 443;

  if (!domain) return NextResponse.json({ error: "domain required" }, { status: 400 });
  if (!/^[a-zA-Z0-9._\-]+$/.test(domain)) {
    return NextResponse.json({ error: "Invalid domain" }, { status: 400 });
  }

  return new Promise<NextResponse>((resolve) => {
    const timer = setTimeout(() => {
      resolve(NextResponse.json({ error: "Connection timed out" }, { status: 200 }));
    }, 12000);

    const socket = tls.connect(port, domain, { servername: domain, rejectUnauthorized: false }, () => {
      clearTimeout(timer);
      const cert = socket.getPeerCertificate(true);
      const authorized = socket.authorized;
      const authError = socket.authorizationError;

      if (!cert || !cert.subject) {
        socket.destroy();
        return resolve(NextResponse.json({ error: "No certificate returned" }, { status: 200 }));
      }

      const now = new Date();
      const validFrom = new Date(cert.valid_from);
      const validTo = new Date(cert.valid_to);
      const daysLeft = Math.floor((validTo.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));

      const result = {
        domain,
        port,
        authorized,
        authError: authorized ? null : authError?.toString(),
        subject: cert.subject,
        issuer: cert.issuer,
        validFrom: cert.valid_from,
        validTo: cert.valid_to,
        daysLeft,
        isExpired: daysLeft < 0,
        isExpiringSoon: daysLeft >= 0 && daysLeft <= 30,
        serialNumber: cert.serialNumber,
        fingerprint: cert.fingerprint,
        fingerprint256: cert.fingerprint256,
        sans: (cert.subjectaltname ?? "").split(", ").filter((s: string) => s.startsWith("DNS:")).map((s: string) => s.replace("DNS:", "")),
        keyBits: cert.bits,
        protocol: socket.getProtocol(),
        cipher: socket.getCipher(),
        chain: buildChain(cert),
      };

      socket.destroy();
      resolve(NextResponse.json(result));
    });

    socket.on("error", (err) => {
      clearTimeout(timer);
      resolve(NextResponse.json({ error: err.message, domain, port }, { status: 200 }));
    });
  });
}

function buildChain(cert: tls.PeerCertificate): Array<{ subject: string; issuer: string; validTo: string }> {
  const chain: Array<{ subject: string; issuer: string; validTo: string }> = [];
  let current: tls.PeerCertificate | null = cert;
  const seen = new Set<string>();

  while (current && !seen.has(current.fingerprint)) {
    seen.add(current.fingerprint);
    chain.push({
      subject: current.subject?.CN ?? JSON.stringify(current.subject),
      issuer: current.issuer?.CN ?? JSON.stringify(current.issuer),
      validTo: current.valid_to,
    });
    const issuerCert = current.issuerCertificate;
    if (!issuerCert || issuerCert === current) break;
    current = issuerCert;
  }

  return chain;
}
