import { handleRouteError, readBody, requirePwAi, resolveProfileContext } from "./agent.shared.js";
import { jsonError, toBoolean, toNumber, toStringOrEmpty } from "./utils.js";
export function registerBrowserAgentStorageRoutes(app, ctx) {
    // Adapter to allow Express-typed handlers when underlying might be browser dispatcher
    const registrar = {
        get: (path, handler) => app.get(path, handler),
        post: (path, handler) => app.post(path, handler),
        delete: (path, handler) => app.delete(path, handler),
    };
    registrar.get("/cookies", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
            const pw = await requirePwAi(res, "cookies");
            if (!pw)
                return;
            const result = await pw.cookiesGetViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
            });
            res.json({ ok: true, targetId: tab.targetId, ...result });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/cookies/set", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const cookie = body.cookie && typeof body.cookie === "object" && !Array.isArray(body.cookie)
            ? body.cookie
            : null;
        if (!cookie)
            return jsonError(res, 400, "cookie is required");
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "cookies set");
            if (!pw)
                return;
            await pw.cookiesSetViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                cookie: {
                    name: toStringOrEmpty(cookie.name),
                    value: toStringOrEmpty(cookie.value),
                    url: toStringOrEmpty(cookie.url) || undefined,
                    domain: toStringOrEmpty(cookie.domain) || undefined,
                    path: toStringOrEmpty(cookie.path) || undefined,
                    expires: toNumber(cookie.expires) ?? undefined,
                    httpOnly: toBoolean(cookie.httpOnly) ?? undefined,
                    secure: toBoolean(cookie.secure) ?? undefined,
                    sameSite: cookie.sameSite === "Lax" || cookie.sameSite === "None" || cookie.sameSite === "Strict"
                        ? cookie.sameSite
                        : undefined,
                },
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/cookies/clear", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "cookies clear");
            if (!pw)
                return;
            await pw.cookiesClearViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.get("/storage/:kind", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const kind = toStringOrEmpty(req.params.kind);
        if (kind !== "local" && kind !== "session")
            return jsonError(res, 400, "kind must be local|session");
        const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
        const key = typeof req.query.key === "string" ? req.query.key : "";
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
            const pw = await requirePwAi(res, "storage get");
            if (!pw)
                return;
            const result = await pw.storageGetViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                kind,
                key: key.trim() || undefined,
            });
            res.json({ ok: true, targetId: tab.targetId, ...result });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/storage/:kind/set", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const kind = toStringOrEmpty(req.params.kind);
        if (kind !== "local" && kind !== "session")
            return jsonError(res, 400, "kind must be local|session");
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const key = toStringOrEmpty(body.key);
        if (!key)
            return jsonError(res, 400, "key is required");
        const value = typeof body.value === "string" ? body.value : "";
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "storage set");
            if (!pw)
                return;
            await pw.storageSetViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                kind,
                key,
                value,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/storage/:kind/clear", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const kind = toStringOrEmpty(req.params.kind);
        if (kind !== "local" && kind !== "session")
            return jsonError(res, 400, "kind must be local|session");
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "storage clear");
            if (!pw)
                return;
            await pw.storageClearViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                kind,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/offline", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const offline = toBoolean(body.offline);
        if (offline === undefined)
            return jsonError(res, 400, "offline is required");
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "offline");
            if (!pw)
                return;
            await pw.setOfflineViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                offline,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/headers", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const headers = body.headers && typeof body.headers === "object" && !Array.isArray(body.headers)
            ? body.headers
            : null;
        if (!headers)
            return jsonError(res, 400, "headers is required");
        const parsed = {};
        for (const [k, v] of Object.entries(headers)) {
            if (typeof v === "string")
                parsed[k] = v;
        }
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "headers");
            if (!pw)
                return;
            await pw.setExtraHTTPHeadersViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                headers: parsed,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/credentials", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const clear = toBoolean(body.clear) ?? false;
        const username = toStringOrEmpty(body.username) || undefined;
        const password = typeof body.password === "string" ? body.password : undefined;
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "http credentials");
            if (!pw)
                return;
            await pw.setHttpCredentialsViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                username,
                password,
                clear,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/geolocation", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const clear = toBoolean(body.clear) ?? false;
        const latitude = toNumber(body.latitude);
        const longitude = toNumber(body.longitude);
        const accuracy = toNumber(body.accuracy) ?? undefined;
        const origin = toStringOrEmpty(body.origin) || undefined;
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "geolocation");
            if (!pw)
                return;
            await pw.setGeolocationViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                latitude,
                longitude,
                accuracy,
                origin,
                clear,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/media", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const schemeRaw = toStringOrEmpty(body.colorScheme);
        const colorScheme = schemeRaw === "dark" || schemeRaw === "light" || schemeRaw === "no-preference"
            ? schemeRaw
            : schemeRaw === "none"
                ? null
                : undefined;
        if (colorScheme === undefined)
            return jsonError(res, 400, "colorScheme must be dark|light|no-preference|none");
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "media emulation");
            if (!pw)
                return;
            await pw.emulateMediaViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                colorScheme,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/timezone", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const timezoneId = toStringOrEmpty(body.timezoneId);
        if (!timezoneId)
            return jsonError(res, 400, "timezoneId is required");
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "timezone");
            if (!pw)
                return;
            await pw.setTimezoneViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                timezoneId,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/locale", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const locale = toStringOrEmpty(body.locale);
        if (!locale)
            return jsonError(res, 400, "locale is required");
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "locale");
            if (!pw)
                return;
            await pw.setLocaleViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                locale,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/set/device", async (req, res) => {
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const name = toStringOrEmpty(body.name);
        if (!name)
            return jsonError(res, 400, "name is required");
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            const pw = await requirePwAi(res, "device emulation");
            if (!pw)
                return;
            await pw.setDeviceViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                name,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            handleRouteError(ctx, res, err);
        }
    });
}
