import { stringify } from "querystring";
import * as request from "request";

import { Article } from "./types";

const URI = "https://api.cardmarket.com/ws/v2.0/output.json";

export class CardMarketApi {
  private AppToken: string;
  private AppSecret: string;
  private AccessToken: string;
  private AccessSecret: string;

  constructor() {
    this.AppToken = process.env.APP_TOKEN;
    this.AppSecret = process.env.APP_SECRET;
    this.AccessToken = process.env.ACCESS_TOKEN;
    this.AccessSecret = process.env.ACCESS_SECRET;
  }

  async request(
    method: string,
    path: string,
    params: Record<string, any> | undefined,
    options: any
  ): Promise<any> {
    const oauth = {
      realm: `${URI}${path}`,
      consumer_key: this.AppToken,
      consumer_secret: this.AppSecret,
      token: this.AccessToken,
      token_secret: this.AccessSecret
    };
    const uri = oauth.realm + (params ? `?${stringify(params)}` : "");
    return new Promise((resolve, reject) => {
      request(
        {
          method,
          uri,
          oauth,
          ...options
        },
        (error, response) => {
          if (error) {
            reject(error);
          } else if (response.statusCode > 299) {
            reject(
              JSON.stringify({
                statusCode: response.statusCode,
                statusMessage: response.statusMessage,
                statusBody: response.body
              })
            );
          }
          try {
            resolve(JSON.parse(response.body));
          } catch (error) {
            reject(error);
          }
        }
      );
    });
  }

  async get(path: string, params?: Record<string, any>): Promise<any> {
    return await this.request("GET", path, params, {});
  }

  async put(
    path: string,
    params?: Record<string, any>,
    data?: string
  ): Promise<any> {
    return await this.request(
      "PUT",
      path,
      params,
      data
        ? {
            body: data
          }
        : {}
    );
  }

  async getAllArticles(uid: string): Promise<Article[]> {
    const perPage = 1000;
    let start = 0;
    let response;
    let data: Article[] = [];
    do {
      response = await this.get(`/users/${uid}/articles`, {
        start,
        maxResults: perPage
      });
      data = data.concat(response.article as Article[]);
      start += response.article.length;
    } while (response.article.length == perPage);
    return data;
  }
}
