/**
 * classify-url.ts
 *
 * Classifies URLs passed via --url/--urls into specific source types.
 * Enables intelligent inference: a Sanity Studio release URL automatically
 * sets the perspective, a Studio document URL extracts the document ID, etc.
 *
 * Classification rules (applied in order):
 *   1. /releases/<id>         → Sanity Release (extract perspective)
 *   2. /structure/...;<uuid>  → Sanity Studio Document (extract doc ID + optional perspective)
 *   3. everything else        → Direct URL (fetch as documentation)
 */
// ---------------------------------------------------------------------------
// Patterns
// ---------------------------------------------------------------------------
/** UUID v4 pattern (case-insensitive) */
const UUID_PATTERN = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
/** Matches /releases/<perspective-id> at the end of a pathname */
const RELEASE_PATH = /\/releases\/([\w-]+)$/;
/**
 * Matches /structure/...;<last-segment> where the last semicolon-delimited
 * segment is extracted. The UUID check is applied separately.
 */
const STRUCTURE_PATH = /\/structure\/.+;([^;?]+)/;
// ---------------------------------------------------------------------------
// Batch classification
// ---------------------------------------------------------------------------
/**
 * Classify a single URL into one of the known source types.
 *
 * @param input - A URL string to classify
 * @returns A discriminated union describing the URL type and extracted metadata
 * @throws If the input is not a valid URL
 */
export function classifyUrl(input) {
    const parsed = new URL(input);
    // Rule 1: Sanity Studio release URL — /releases/<perspective-id>
    const releaseMatch = parsed.pathname.match(RELEASE_PATH);
    if (releaseMatch) {
        return {
            perspectiveId: releaseMatch[1],
            studioOrigin: parsed.origin,
            type: "sanity-release",
        };
    }
    // Rule 2: Sanity Studio document URL — /structure/...;<uuid>
    const structureMatch = parsed.pathname.match(STRUCTURE_PATH);
    if (structureMatch && UUID_PATTERN.test(structureMatch[1])) {
        return {
            documentId: structureMatch[1],
            perspectiveId: parsed.searchParams.get("perspective") ?? undefined,
            studioOrigin: parsed.origin,
            type: "sanity-document",
        };
    }
    // Rule 3: Default — direct documentation URL
    return { type: "direct-url", url: input };
}
/**
 * Classify an array of URLs and aggregate the results.
 *
 * Collects direct URLs and document IDs into separate lists. Perspective
 * and studio origin are inferred from the first Sanity URL that provides them.
 *
 * @param urls - Array of URL strings to classify
 * @returns Aggregated classification result
 */
export function classifyUrls(urls) {
    const result = {
        directUrls: [],
        documentIds: [],
    };
    for (const url of urls) {
        const classified = classifyUrl(url);
        switch (classified.type) {
            case "direct-url":
                result.directUrls.push(classified.url);
                break;
            case "sanity-document":
                result.documentIds.push(classified.documentId);
                if (classified.perspectiveId && !result.inferredPerspective) {
                    result.inferredPerspective = classified.perspectiveId;
                }
                result.inferredStudioOrigin ??= classified.studioOrigin;
                break;
            case "sanity-release":
                result.inferredPerspective ??= classified.perspectiveId;
                result.inferredStudioOrigin ??= classified.studioOrigin;
                break;
        }
    }
    return result;
}
