package com.correx.apps.server.research

import java.net.URI

/**
 * Pure host extraction for batch source-list approval (BACKLOG §D). Given the URLs (or dossier
 * source lines) of a research source list, returns the distinct, lower-cased hostnames the operator
 * is approving egress to — the input set for a single [com.correx.core.events.events.EgressHostsGrantedEvent].
 *
 * Mirrors [com.correx.core.toolintent.rules.NetworkHostRule]'s URL parsing so the granted hosts line
 * up with what the network gate later matches: absolute URLs only (`scheme://host`), parsed via
 * [java.net.URI], host lower-cased, port dropped (URI.host excludes it). Entries that don't parse to
 * a host — relative paths, free text, malformed URLs — are ignored rather than failing the batch.
 *
 * source_dossier entries start with the URL but may carry a trailing note
 * ("https://example.com/x — explains Y"); the leading whitespace-delimited token is taken so those
 * lines still yield their host.
 */
object SourceListHosts {

    /**
     * The distinct lower-cased hostnames drawn from [urls]. Deterministic; unparseable/relative
     * entries are skipped. Duplicate hosts (and differing-case or differing-port variants of the
     * same host) collapse to one.
     */
    fun extract(urls: List<String>): Set<String> =
        urls.mapNotNullTo(LinkedHashSet()) { hostOf(it) }

    private fun hostOf(raw: String): String? {
        val token = raw.trim().substringBefore(' ').substringBefore('\t')
        if (!token.contains("://")) return null
        return runCatching { URI(token).host?.lowercase() }.getOrNull()?.takeIf { it.isNotEmpty() }
    }
}
