// retoor <retoor@molodetz.nl>

export class DevRant {
  constructor(baseUrl, username, password) {
    this.baseUrl = baseUrl.replace(/\/$/, "");
    this.username = username;
    this.password = password;
    this.auth = {};
  }

  _url(path, params) {
    const url = new URL(`${this.baseUrl}/api/${path.replace(/^\//, "")}`);
    for (const [key, value] of Object.entries(params || {})) {
      url.searchParams.set(key, value);
    }
    return url;
  }

  async _request(method, path, params = {}, body = null) {
    const merged = { ...params, ...this.auth };
    const headers = { Accept: "application/json" };
    let url;
    const init = { method, headers };
    if (method === "GET" || method === "DELETE") {
      url = this._url(path, merged);
    } else {
      url = this._url(path);
      headers["Content-Type"] = "application/x-www-form-urlencoded";
      init.body = new URLSearchParams({ ...merged, ...(body || {}) }).toString();
    }
    const response = await fetch(url, init);
    return response.json();
  }

  async login() {
    const result = await this._request("POST", "users/auth-token", {}, {
      username: this.username,
      password: this.password,
    });
    if (!result.success) throw new Error(result.error || "login failed");
    const token = result.auth_token;
    this.auth = { user_id: token.user_id, token_id: token.id, token_key: token.key };
    return this.auth;
  }

  register(email) {
    return this._request("POST", "users", {}, {
      username: this.username,
      email,
      password: this.password,
    });
  }

  async rants(sort = "recent", limit = 20, skip = 0) {
    const result = await this._request("GET", "devrant/rants", { sort, limit, skip });
    return result.rants || [];
  }

  rant(rantId) {
    return this._request("GET", `devrant/rants/${rantId}`);
  }

  async search(term) {
    return (await this._request("GET", "devrant/search", { term })).results || [];
  }

  async userId(username) {
    return (await this._request("GET", "get-user-id", { username })).user_id;
  }

  async profile(userId) {
    return (await this._request("GET", `users/${userId}`)).profile;
  }

  async notifs() {
    return (await this._request("GET", "users/me/notif-feed")).data || {};
  }

  clearNotifs() {
    return this._request("DELETE", "users/me/notif-feed");
  }

  editProfile(fields) {
    return this._request("POST", "users/me/edit-profile", {}, fields);
  }

  postRant(text, tags = "") {
    return this._request("POST", "devrant/rants", {}, { rant: text, tags });
  }

  editRant(rantId, text, tags = "") {
    return this._request("POST", `devrant/rants/${rantId}`, {}, { rant: text, tags });
  }

  deleteRant(rantId) {
    return this._request("DELETE", `devrant/rants/${rantId}`);
  }

  voteRant(rantId, vote) {
    return this._request("POST", `devrant/rants/${rantId}/vote`, {}, { vote });
  }

  favorite(rantId) {
    return this._request("POST", `devrant/rants/${rantId}/favorite`);
  }

  unfavorite(rantId) {
    return this._request("POST", `devrant/rants/${rantId}/unfavorite`);
  }

  comment(rantId, text) {
    return this._request("POST", `devrant/rants/${rantId}/comments`, {}, { comment: text });
  }

  voteComment(commentId, vote) {
    return this._request("POST", `comments/${commentId}/vote`, {}, { vote });
  }
}

export function fromEnv() {
  return new DevRant(
    process.env.DEVRANT_BASE || "http://localhost:10500",
    process.env.DEVRANT_USERNAME,
    process.env.DEVRANT_PASSWORD,
  );
}
