import { ERouteHttpVerb } from "@devowl-wp/api";

import type { RouteResponseInterface } from "./commonUrlBuilder.js";

/**
 * Get the result of the `Response`. It also handles multiline responses, e. g.
 * a PHP `Notice:` message is output through a conflicting plugin:
 *
 * If you are using a verb like `DELETE` or `PUT` the response may be empty and this
 * function will return `undefined`.
 *
 * @see https://developer.mozilla.org/de/docs/Web/HTTP/Methods/DELETE
 */
async function parseResult<TResponse extends RouteResponseInterface>(
    url: string,
    result: Response,
    method?: ERouteHttpVerb,
) {
    // A `204 No content` response has no body, so we do not need to parse anything
    if (result.status === 204) {
        return {} as TResponse;
    }

    const cloneForFallback = result.clone();
    try {
        return (await result.json()) as TResponse;
    } catch (e) {
        // Something went wrong, try each line as result of a JSON string
        const body = await cloneForFallback.text();

        // Respect empty responses for given verbs (DELETE, PUT)
        if (body === "" && [ERouteHttpVerb.DELETE, ERouteHttpVerb.PUT].indexOf(method) > -1) {
            return undefined;
        }

        console.warn(`The response of ${url} contains unexpected JSON, try to resolve the JSON line by line...`, {
            body,
        });
        let lastError: any;
        for (const line of body.split("\n")) {
            if (line.startsWith("[") || line.startsWith("{")) {
                try {
                    return JSON.parse(line) as TResponse;
                } catch (e) {
                    lastError = e;
                }
            }
        }
        throw lastError;
    }
}

export { parseResult };
