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

/**
 * Edge middleware that establishes workspace context from the request Host
 * when a visitor lands on <subdomain>.reparee.com WITHOUT a prior handoff.
 *
 * - Skips if the workspace_uuid cookie is already set (handoff already happened).
 * - Skips for the shared fallback host `tenant.reparee.com` and any non-tenant
 *   host (apex, localhost, preview URLs).
 * - For a tenant subdomain, HMAC-signs the subdomain and calls SaaS
 *   `GET /api/saas/workspaces/by-subdomain/<sub>` to resolve to
 *   { workspace_uuid, api_base_url }, then sets those as HttpOnly cookies.
 *
 * Matcher excludes /api/proxy/* (proxy needs no resolution; cookies already set)
 * and /activate/* (the handoff itself sets the cookies via the page handler).
 */
export const config = {
    matcher: [
        "/((?!api/proxy|_next/static|_next/image|favicon\\.ico|robots\\.txt|sitemap\\.xml|activate).*)",
    ],
}

const SUBDOMAIN_RE = /^([a-z0-9-]+)\.reparee\.com$/i
const SKIP_SUBDOMAINS = new Set(["tenant", "www"])
const COOKIE_MAX_AGE = 60 * 60 * 24 * 7 // 7 days

export async function middleware(req: NextRequest) {
    if (req.cookies.get("workspace_uuid")) {
        return NextResponse.next()
    }

    const host = (req.headers.get("host") || "").toLowerCase()
    const match = host.match(SUBDOMAIN_RE)
    if (!match) return NextResponse.next()

    const sub = match[1].toLowerCase()
    if (SKIP_SUBDOMAINS.has(sub)) return NextResponse.next()

    const saasUrl = process.env.NEXT_PUBLIC_SAAS_URL || "https://reparee.com"
    const secret = process.env.SAAS_SHARED_SECRET || ""
    if (!secret) {
        return NextResponse.next()
    }

    let workspaceUuid: string | undefined
    let apiBaseUrl: string | undefined

    try {
        const signature = await hmacSha256Hex(sub, secret)
        const resolveUrl = `${saasUrl.replace(/\/$/, "")}/api/saas/workspaces/by-subdomain/${encodeURIComponent(sub)}`
        const res = await fetch(resolveUrl, {
            headers: { "X-SaaS-Signature": signature, Accept: "application/json" },
            cache: "no-store",
            signal: AbortSignal.timeout(2500),
        })
        if (!res.ok) return NextResponse.next()

        const data = (await res.json()) as { ok?: boolean; workspace_uuid?: string; api_base_url?: string }
        if (!data.ok || !data.workspace_uuid || !data.api_base_url) {
            return NextResponse.next()
        }
        workspaceUuid = data.workspace_uuid
        apiBaseUrl = data.api_base_url
    } catch {
        return NextResponse.next()
    }

    const response = NextResponse.next()
    response.cookies.set("workspace_uuid", workspaceUuid!, {
        httpOnly: true,
        secure: true,
        sameSite: "strict",
        path: "/",
        maxAge: COOKIE_MAX_AGE,
    })
    response.cookies.set("api_base_url", apiBaseUrl!, {
        httpOnly: true,
        secure: true,
        sameSite: "strict",
        path: "/",
        maxAge: COOKIE_MAX_AGE,
    })
    return response
}

async function hmacSha256Hex(message: string, key: string): Promise<string> {
    const enc = new TextEncoder()
    const cryptoKey = await crypto.subtle.importKey(
        "raw",
        enc.encode(key),
        { name: "HMAC", hash: "SHA-256" },
        false,
        ["sign"],
    )
    const sig = await crypto.subtle.sign("HMAC", cryptoKey, enc.encode(message))
    return Array.from(new Uint8Array(sig))
        .map((b) => b.toString(16).padStart(2, "0"))
        .join("")
}
