/**
 * @license
 * Copyright 2024 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {getBaseUrl} from '../../../../utils/url-util';
import {AuthService} from '../../../../services/gr-auth/gr-auth';
import {ParsedJSON, RequestPayload} from '../../../../types/common';
import {HttpMethod} from '../../../../constants/constants';
import {RpcLogEventDetail} from '../../../../types/events';
import {
  fire,
  fireNetworkError,
  fireServerError,
} from '../../../../utils/event-util';
import {
  AuthRequestInit,
  FetchRequest as FetchRequestBase,
} from '../../../../types/types';
import {ErrorCallback} from '../../../../api/rest';
import {Scheduler, Task} from '../../../../services/scheduler/scheduler';
import {RetryError} from '../../../../services/scheduler/retry-scheduler';

export const JSON_PREFIX = ")]}'";

export interface ResponsePayload {
  parsed: ParsedJSON;
  raw: string;
}

export async function readJSONResponsePayload(
  response: Response
): Promise<ResponsePayload> {
  const text = await response.text();
  let result: ParsedJSON;
  try {
    result = parsePrefixedJSON(text);
  } catch (_) {
    throw new Error(`Response payload is not prefixed json. Payload: ${text}`);
  }
  return {parsed: result!, raw: text};
}

export function parsePrefixedJSON(jsonWithPrefix: string): ParsedJSON {
  return JSON.parse(jsonWithPrefix.substring(JSON_PREFIX.length)) as ParsedJSON;
}

/**
 * Wrapper around Map for caching server responses. Site-based so that
 * changes to CANONICAL_PATH will result in a different cache going into
 * effect.
 *
 * All methods operate on the cache for the current CANONICAL_PATH.
 * Accessing cache entries for older CANONICAL_PATH not supported.
 */
// TODO(kamilm): Seems redundant to have both this and FetchPromisesCache
//   consider joining their functionality into a single cache.
export class SiteBasedCache {
  private readonly data = new Map<string, Map<string, ParsedJSON>>();

  constructor() {
    if (window.INITIAL_DATA) {
      // Put all data shipped with index.html into the cache. This makes it
      // so that we spare more round trips to the server when the app loads
      // initially.
      // TODO(kamilm): This implies very strict format of what is stored in
      //   INITIAL_DATA which is not clear from the name, consider renaming.
      Object.entries(window.INITIAL_DATA).forEach(e =>
        this._cache().set(e[0], e[1] as unknown as ParsedJSON)
      );
    }
  }

  // Returns the cache for the current canonical path.
  _cache(): Map<string, ParsedJSON> {
    const canonical_path = window.CANONICAL_PATH ?? '';
    if (!this.data.has(canonical_path)) {
      this.data.set(canonical_path, new Map<string, ParsedJSON>());
    }
    return this.data.get(canonical_path)!;
  }

  has(key: string) {
    return this._cache().has(key);
  }

  get(key: string): ParsedJSON | undefined {
    return this._cache().get(key);
  }

  set(key: string, value: ParsedJSON) {
    this._cache().set(key, value);
  }

  delete(key: string) {
    this._cache().delete(key);
  }

  invalidatePrefix(prefix: string) {
    const newMap = new Map<string, ParsedJSON>();
    for (const [key, value] of this._cache().entries()) {
      if (!key.startsWith(prefix)) {
        newMap.set(key, value);
      }
    }
    this.data.set(window.CANONICAL_PATH ?? '', newMap);
  }
}

type FetchPromisesCacheData = {
  [url: string]: Promise<ParsedJSON | undefined> | undefined;
};

/**
 * Stores promises for inflight requests, by url.
 */
export class FetchPromisesCache {
  private data: FetchPromisesCacheData;

  constructor() {
    this.data = {};
  }

  public testOnlyGetData() {
    return this.data;
  }

  /**
   * @return true only if a value for a key sets and it is not undefined
   */
  has(key: string): boolean {
    return !!this.data[key];
  }

  get(key: string) {
    return this.data[key];
  }

  /**
   * @param value a Promise to store in the cache. Pass undefined value to
   *     mark key as deleted.
   */
  set(key: string, value: Promise<ParsedJSON | undefined> | undefined) {
    this.data[key] = value;
  }

  invalidatePrefix(prefix: string) {
    const newData: FetchPromisesCacheData = {};
    Object.entries(this.data).forEach(([key, value]) => {
      if (!key.startsWith(prefix)) {
        newData[key] = value;
      }
    });
    this.data = newData;
  }
}

export type FetchParams = {
  [name: string]: string[] | string | number | boolean | undefined | null;
};

/**
 * Error callback that throws an error.
 *
 * Pass into REST API methods as errFn to make the returned Promises reject on
 * error.
 *
 * If error is provided, it's thrown.
 * Otherwise if response with error is provided the promise that will throw an
 * error is returned.
 */
export function throwingErrorCallback(
  response?: Response | null,
  err?: Error
): void | Promise<void> {
  if (err) throw err;
  if (!response) return;

  return response.text().then(errorText => {
    let message = `Error ${response.status}`;
    if (response.statusText) {
      message += ` (${response.statusText})`;
    }
    if (errorText) {
      message += `: ${errorText}`;
    }
    throw new Error(message);
  });
}

export interface FetchRequest extends FetchRequestBase {
  /**
   * If neither this or anonymizedUrl specified no 'gr-rpc-log' event is fired.
   */
  reportUrlAsIs?: boolean;
  /** Extra url params to be encoded and added to the url. */
  params?: FetchParams;
  /**
   * Callback that is called, if an error was caught during fetch or if the
   * response was returned with a non-2xx status.
   */
  errFn?: ErrorCallback;
  /**
   * If true, response with non-200 status will cause an error to be reported
   * via server-error event or errFn, if provided.
   */
  // TODO(kamilm): Consider changing the default to true. It makes more sense to
  //   only skip the check if the caller wants to prosess status themselves.
  reportServerError?: boolean;
}

export interface FetchOptionsInit {
  method?: HttpMethod;
  body?: RequestPayload;
  contentType?: string;
  headers?: Record<string, string>;
}

export function getFetchOptions(init: FetchOptionsInit): AuthRequestInit {
  const options: AuthRequestInit = {
    method: init.method,
  };
  if (init.body) {
    options.headers = new Headers();
    options.headers.set('Content-Type', init.contentType || 'application/json');
    options.body =
      typeof init.body === 'string' ? init.body : JSON.stringify(init.body);
  }
  // Copy headers after processing body, so that explicit headers can override
  // if necessary.
  if (init.headers) {
    if (!options.headers) {
      options.headers = new Headers();
    }
    for (const [name, value] of Object.entries(init.headers)) {
      options.headers.set(name, value);
    }
  }
  return options;
}

export class GrRestApiHelper {
  constructor(
    private readonly _cache: SiteBasedCache,
    private readonly _auth: AuthService,
    private readonly _fetchPromisesCache: FetchPromisesCache,
    private readonly readScheduler: Scheduler<Response>,
    private readonly writeScheduler: Scheduler<Response>
  ) {}

  private schedule(method: string, task: Task<Response>): Promise<Response> {
    if (method === 'PUT' || method === 'POST' || method === 'DELETE') {
      return this.writeScheduler.schedule(task);
    } else {
      return this.readScheduler.schedule(task);
    }
  }

  /**
   * Wraps calls to the underlying authenticated fetch function (_auth.fetch)
   * with timing and logging.
   */
  private fetchImpl(req: FetchRequest): Promise<Response> {
    const method = req.fetchOptions?.method ?? HttpMethod.GET;
    const startTime = Date.now();
    const task = async () => {
      const res = await this._auth.fetch(req.url, req.fetchOptions);
      // Check for "too many requests" error and throw RetryError to cause a
      // retry in this case, if the scheduler attempts retries.
      if (!res.ok && res.status === 429) throw new RetryError<Response>(res);
      return res;
    };

    const resPromise = this.schedule(method, task).catch((err: unknown) => {
      if (err instanceof RetryError) {
        return err.payload;
      } else {
        throw err;
      }
    });

    // Log the call after it completes.
    resPromise.then(res => this.logCall(req, startTime, res.status));
    // Return the response directly (without the log).
    return resPromise;
  }

  /**
   * Log information about a REST call. Because the elapsed time is determined
   * by this method, it should be called immediately after the request
   * finishes.
   *
   * Private, but used in tests.
   *
   * @param startTime the time that the request was started.
   * @param status the HTTP status of the response. The status value
   *     is used here rather than the response object so there is no way this
   *     method can read the body stream.
   */
  logCall(req: FetchRequest, startTime: number, status: number) {
    const method =
      req.fetchOptions && req.fetchOptions.method
        ? req.fetchOptions.method
        : 'GET';
    const endTime = Date.now();
    const elapsed = endTime - startTime;
    const startAt = new Date(startTime);
    const endAt = new Date(endTime);
    console.debug(
      [
        'HTTP',
        status,
        method,
        `${elapsed}ms`,
        req.anonymizedUrl || req.url,
        `(${startAt.toISOString()}, ${endAt.toISOString()})`,
      ].join(' ')
    );
    if (req.anonymizedUrl) {
      const detail: RpcLogEventDetail = {
        status,
        method,
        elapsed,
        anonymizedUrl: req.anonymizedUrl,
      };
      fire(document, 'gr-rpc-log', detail);
    }
  }

  /**
   * Fetch from url provided.
   *
   * Performs auth. Validates auth expiry errors.
   * Will report any errors (by firing a corresponding event or calling errFn)
   * that happen during the request, but doesn't inspect the status of the
   * received response unless req.reportServerError = true.
   *
   * @return Promise resolves to a native Response.
   *     If an error occurs when performing a request, promise rejects.
   */
  async fetch(req: FetchRequest): Promise<Response> {
    const urlWithParams = this.urlWithParams(req.url, req.params);
    const fetchReq: FetchRequest = {
      url: urlWithParams,
      fetchOptions: req.fetchOptions,
      anonymizedUrl: req.reportUrlAsIs ? urlWithParams : req.anonymizedUrl,
    };
    let resp: Response;
    try {
      resp = await this.fetchImpl(fetchReq);
    } catch (err) {
      if (req.errFn) {
        await req.errFn.call(undefined, null, err as Error);
      } else {
        fireNetworkError(err as Error);
      }
      throw err;
    }
    if (req.reportServerError && !resp.ok) {
      if (req.errFn) {
        await req.errFn.call(undefined, resp);
      } else {
        fireServerError(resp, req);
      }
    }
    return resp;
  }

  /**
   * Fetch JSON from url provided.
   *
   * Returned promise rejects if an error occurs when performing a request or
   * if the response payload doesn't contain a valid prefixed JSON.
   *
   * If response status is not 2xx, promise resolves to undefined and error is
   * reported, through errFn callback or via 'sever-error' event. The error can
   * be suppressed with req.reportServerError = false.
   *
   * If JSON parsing fails the promise rejects.
   *
   * @param noAcceptHeader - don't add default accept json header
   * @return Promise that resolves to a parsed response.
   */
  async fetchJSON(
    req: FetchRequest,
    noAcceptHeader?: boolean
  ): Promise<ParsedJSON | undefined> {
    if (!noAcceptHeader) {
      req = this.addAcceptJsonHeader(req);
    }
    req.reportServerError ??= true;
    const response = await this.fetch(req);
    if (!response.ok) {
      return undefined;
    }
    // TODO(kamilm): The parsing error should likely be reported via errFn or
    // gr-error-manager as well.
    return (await readJSONResponsePayload(response)).parsed;
  }

  /**
   * Add extra url params to the url.
   *
   * Params with values (not undefined) added as <key>=<value>. If value is an
   * array a separate <key>=<value> param is added for every value.
   */
  urlWithParams(url: string, fetchParams?: FetchParams): string {
    if (!fetchParams) {
      return getBaseUrl() + url;
    }

    const params: Array<string | number | boolean> = [];
    for (const [paramKey, paramValue] of Object.entries(fetchParams)) {
      if (paramValue === null || paramValue === undefined) {
        params.push(this.encodeRFC5987(paramKey));
        continue;
      }

      if (Array.isArray(paramValue)) {
        for (const value of paramValue) {
          params.push(
            `${this.encodeRFC5987(paramKey)}=${this.encodeRFC5987(value)}`
          );
        }
      } else {
        params.push(
          `${this.encodeRFC5987(paramKey)}=${this.encodeRFC5987(paramValue)}`
        );
      }
    }
    return getBaseUrl() + url + '?' + params.join('&');
  }

  // Backend encode url in RFC5987 and frontend needs to do same to match
  // queries for preloading queries
  encodeRFC5987(uri: string | number | boolean) {
    return encodeURIComponent(uri).replace(
      /['()*]/g,
      c => '%' + c.charCodeAt(0).toString(16)
    );
  }

  addAcceptJsonHeader(req: FetchRequest) {
    if (!req.fetchOptions) req.fetchOptions = {};
    if (!req.fetchOptions.headers) req.fetchOptions.headers = new Headers();
    if (!req.fetchOptions.headers.has('Accept')) {
      req.fetchOptions.headers.append('Accept', 'application/json');
    }
    return req;
  }

  /**
   * Fetch JSON using cached value if available.
   *
   * If there is an in-flight request with the same url returns the promise for
   * the in-flight request. If previous call for the same url resulted in the
   * successful response it is returned. Otherwise a new request is sent.
   *
   * Only req.url with req.params is considered for the caching key;
   * headers or request body are not included in cache key.
   */
  fetchCacheJSON(req: FetchRequest): Promise<ParsedJSON | undefined> {
    const urlWithParams = this.urlWithParams(req.url, req.params);
    if (this._fetchPromisesCache.has(urlWithParams)) {
      return this._fetchPromisesCache.get(urlWithParams)!;
    }
    if (this._cache.has(urlWithParams)) {
      return Promise.resolve(this._cache.get(urlWithParams)!);
    }
    this._fetchPromisesCache.set(
      urlWithParams,
      this.fetchJSON(req)
        .then(response => {
          if (response !== undefined) {
            this._cache.set(urlWithParams, response);
          }
          this._fetchPromisesCache.set(urlWithParams, undefined);
          return response;
        })
        .catch(err => {
          this._fetchPromisesCache.set(urlWithParams, undefined);
          throw err;
        })
    );
    return this._fetchPromisesCache.get(urlWithParams)!;
  }

  invalidateFetchPromisesPrefix(prefix: string) {
    this._fetchPromisesCache.invalidatePrefix(prefix);
    this._cache.invalidatePrefix(prefix);
  }
}
